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 = 670 dvmAllocObject(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember, 671 ALLOC_DEFAULT); 672 name = dexStringById(pDexFile, elementNameIdx); 673 nameObj = dvmCreateStringFromCstr(name); 674 675 /* find the method in the annotation class, given only the name */ 676 if (name != NULL) { 677 Method* annoMeth = dvmFindVirtualMethodByName(annoClass, name); 678 if (annoMeth == NULL) { 679 ALOGW("WARNING: could not find annotation member %s in %s", 680 name, annoClass->descriptor); 681 } else { 682 methodObj = dvmCreateReflectObjForMethod(annoClass, annoMeth); 683 methodReturn = dvmGetBoxedReturnType(annoMeth); 684 } 685 } 686 if (newMember == NULL || nameObj == NULL || methodObj == NULL || 687 methodReturn == NULL) 688 { 689 ALOGE("Failed creating annotation element (m=%p n=%p a=%p r=%p)", 690 newMember, nameObj, methodObj, methodReturn); 691 goto bail; 692 } 693 694 /* convert the return type, if necessary */ 695 valueObj = convertReturnType(valueObj, methodReturn); 696 if (valueObj == NULL) 697 goto bail; 698 699 /* call 4-argument constructor */ 700 dvmCallMethod(self, gDvm.methOrgApacheHarmonyLangAnnotationAnnotationMember_init, 701 newMember, &unused, nameObj, valueObj, methodReturn, methodObj); 702 if (dvmCheckException(self)) { 703 ALOGD("Failed constructing annotation element"); 704 goto bail; 705 } 706 707 failed = false; 708 709 bail: 710 /* release tracked allocations */ 711 dvmReleaseTrackedAlloc(newMember, self); 712 dvmReleaseTrackedAlloc((Object*)nameObj, self); 713 dvmReleaseTrackedAlloc(valueObj, self); 714 dvmReleaseTrackedAlloc(methodObj, self); 715 if (failed) 716 return NULL; 717 else 718 return newMember; 719 } 720 721 /* 722 * Create a new Annotation object from what we find in the annotation item. 723 * 724 * "clazz" is the class on which the annotations are defined. "pPtr" 725 * points to a pointer into the annotation data. 726 * 727 * We use the AnnotationFactory class to create the annotation for us. The 728 * method we call is: 729 * 730 * public static Annotation createAnnotation( 731 * Class<? extends Annotation> annotationType, 732 * AnnotationMember[] elements) 733 * 734 * Returns a new Annotation, which will NOT be in the local ref table and 735 * not referenced elsewhere, so store it away soon. On failure, returns NULL 736 * with an exception raised. 737 */ 738 static Object* processEncodedAnnotation(const ClassObject* clazz, 739 const u1** pPtr) 740 { 741 Thread* self = dvmThreadSelf(); 742 Object* newAnno = NULL; 743 ArrayObject* elementArray = NULL; 744 const ClassObject* annoClass; 745 const u1* ptr; 746 u4 typeIdx, size, count; 747 748 ptr = *pPtr; 749 typeIdx = readUleb128(&ptr); 750 size = readUleb128(&ptr); 751 752 LOGVV("----- processEnc ptr=%p type=%d size=%d", ptr, typeIdx, size); 753 754 annoClass = dvmDexGetResolvedClass(clazz->pDvmDex, typeIdx); 755 if (annoClass == NULL) { 756 annoClass = dvmResolveClass(clazz, typeIdx, true); 757 if (annoClass == NULL) { 758 ALOGE("Unable to resolve %s annotation class %d", 759 clazz->descriptor, typeIdx); 760 assert(dvmCheckException(self)); 761 dvmClearException(self); 762 return NULL; 763 } 764 } 765 766 ALOGV("----- processEnc ptr=%p [0x%06x] typeIdx=%d size=%d class=%s", 767 *pPtr, *pPtr - (u1*) clazz->pDvmDex->pDexFile->baseAddr, 768 typeIdx, size, annoClass->descriptor); 769 770 /* 771 * Elements are parsed out and stored in an array. The Harmony 772 * constructor wants an array with just the declared elements -- 773 * default values get merged in later. 774 */ 775 JValue result; 776 777 if (size > 0) { 778 elementArray = dvmAllocArrayByClass( 779 gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMemberArray, 780 size, ALLOC_DEFAULT); 781 if (elementArray == NULL) { 782 ALOGE("failed to allocate annotation member array (%d elements)", 783 size); 784 goto bail; 785 } 786 } 787 788 /* 789 * "ptr" points to a byte stream with "size" occurrences of 790 * annotation_element. 791 */ 792 for (count = 0; count < size; count++) { 793 Object* newMember = createAnnotationMember(clazz, annoClass, &ptr); 794 if (newMember == NULL) 795 goto bail; 796 797 /* add it to the array */ 798 dvmSetObjectArrayElement(elementArray, count, newMember); 799 } 800 801 dvmCallMethod(self, 802 gDvm.methOrgApacheHarmonyLangAnnotationAnnotationFactory_createAnnotation, 803 NULL, &result, annoClass, elementArray); 804 if (dvmCheckException(self)) { 805 ALOGD("Failed creating an annotation"); 806 //dvmLogExceptionStackTrace(); 807 goto bail; 808 } 809 810 newAnno = (Object*)result.l; 811 812 bail: 813 dvmReleaseTrackedAlloc((Object*) elementArray, NULL); 814 *pPtr = ptr; 815 if (newAnno == NULL && !dvmCheckException(self)) { 816 /* make sure an exception is raised */ 817 dvmThrowRuntimeException("failure in processEncodedAnnotation"); 818 } 819 return newAnno; 820 } 821 822 /* 823 * Run through an annotation set and convert each entry into an Annotation 824 * object. 825 * 826 * Returns an array of Annotation objects, or NULL with an exception raised 827 * on alloc failure. 828 */ 829 static ArrayObject* processAnnotationSet(const ClassObject* clazz, 830 const DexAnnotationSetItem* pAnnoSet, int visibility) 831 { 832 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 833 const DexAnnotationItem* pAnnoItem; 834 835 /* we need these later; make sure they're initialized */ 836 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory)) 837 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory); 838 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember)) 839 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember); 840 841 /* count up the number of visible elements */ 842 size_t count = 0; 843 for (size_t i = 0; i < pAnnoSet->size; ++i) { 844 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i); 845 if (pAnnoItem->visibility == visibility) { 846 count++; 847 } 848 } 849 850 ArrayObject* annoArray = dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArray, 851 count, ALLOC_DEFAULT); 852 if (annoArray == NULL) { 853 return NULL; 854 } 855 856 /* 857 * Generate Annotation objects. We must put them into the array 858 * immediately (or add them to the tracked ref table). 859 * We may not be able to resolve all annotations, and should just 860 * ignore those we can't. 861 */ 862 u4 dstIndex = 0; 863 for (int i = 0; i < (int) pAnnoSet->size; i++) { 864 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i); 865 if (pAnnoItem->visibility != visibility) 866 continue; 867 const u1* ptr = pAnnoItem->annotation; 868 Object *anno = processEncodedAnnotation(clazz, &ptr); 869 if (anno != NULL) { 870 dvmSetObjectArrayElement(annoArray, dstIndex, anno); 871 ++dstIndex; 872 } 873 } 874 875 // If we got as many as we expected, we're done... 876 if (dstIndex == count) { 877 return annoArray; 878 } 879 880 // ...otherwise we need to trim the trailing nulls. 881 ArrayObject* trimmedArray = dvmAllocArrayByClass(gDvm.classJavaLangAnnotationAnnotationArray, 882 dstIndex, ALLOC_DEFAULT); 883 if (trimmedArray == NULL) { 884 return NULL; 885 } 886 for (size_t i = 0; i < dstIndex; ++i) { 887 Object** src = (Object**)(void*) annoArray->contents; 888 dvmSetObjectArrayElement(trimmedArray, i, src[i]); 889 } 890 dvmReleaseTrackedAlloc((Object*) annoArray, NULL); 891 return trimmedArray; 892 } 893 894 /* 895 * Return the annotation item of the specified type in the annotation set, or 896 * NULL if the set contains no annotation of that type. 897 */ 898 static const DexAnnotationItem* getAnnotationItemFromAnnotationSet( 899 const ClassObject* clazz, const DexAnnotationSetItem* pAnnoSet, 900 int visibility, const ClassObject* annotationClazz) 901 { 902 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 903 const DexAnnotationItem* pAnnoItem; 904 int i; 905 const ClassObject* annoClass; 906 const u1* ptr; 907 u4 typeIdx; 908 909 /* we need these later; make sure they're initialized */ 910 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory)) 911 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationFactory); 912 if (!dvmIsClassInitialized(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember)) 913 dvmInitClass(gDvm.classOrgApacheHarmonyLangAnnotationAnnotationMember); 914 915 for (i = 0; i < (int) pAnnoSet->size; i++) { 916 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i); 917 if (pAnnoItem->visibility != visibility) 918 continue; 919 920 ptr = pAnnoItem->annotation; 921 typeIdx = readUleb128(&ptr); 922 923 annoClass = dvmDexGetResolvedClass(clazz->pDvmDex, typeIdx); 924 if (annoClass == NULL) { 925 annoClass = dvmResolveClass(clazz, typeIdx, true); 926 if (annoClass == NULL) { 927 ALOGE("Unable to resolve %s annotation class %d", 928 clazz->descriptor, typeIdx); 929 Thread* self = dvmThreadSelf(); 930 assert(dvmCheckException(self)); 931 dvmClearException(self); 932 continue; 933 } 934 } 935 936 if (annoClass == annotationClazz) { 937 return pAnnoItem; 938 } 939 } 940 941 return NULL; 942 } 943 944 /* 945 * Return the Annotation object of the specified type in the annotation set, or 946 * NULL if the set contains no annotation of that type. 947 */ 948 static Object* getAnnotationObjectFromAnnotationSet(const ClassObject* clazz, 949 const DexAnnotationSetItem* pAnnoSet, int visibility, 950 const ClassObject* annotationClazz) 951 { 952 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet( 953 clazz, pAnnoSet, visibility, annotationClazz); 954 if (pAnnoItem == NULL) { 955 return NULL; 956 } 957 const u1* ptr = pAnnoItem->annotation; 958 return processEncodedAnnotation(clazz, &ptr); 959 } 960 961 /* 962 * =========================================================================== 963 * Skipping and scanning 964 * =========================================================================== 965 */ 966 967 /* 968 * Skip past an annotation value. 969 * 970 * "clazz" is the class on which the annotations are defined. 971 * 972 * Returns "true" on success, "false" on parsing failure. 973 */ 974 static bool skipAnnotationValue(const ClassObject* clazz, const u1** pPtr) 975 { 976 const u1* ptr = *pPtr; 977 u1 valueType, valueArg; 978 int width; 979 980 valueType = *ptr++; 981 valueArg = valueType >> kDexAnnotationValueArgShift; 982 width = valueArg + 1; /* assume */ 983 984 ALOGV("----- type is 0x%02x %d, ptr=%p [0x%06x]", 985 valueType & kDexAnnotationValueTypeMask, valueArg, ptr-1, 986 (ptr-1) - (u1*)clazz->pDvmDex->pDexFile->baseAddr); 987 988 switch (valueType & kDexAnnotationValueTypeMask) { 989 case kDexAnnotationByte: break; 990 case kDexAnnotationShort: break; 991 case kDexAnnotationChar: break; 992 case kDexAnnotationInt: break; 993 case kDexAnnotationLong: break; 994 case kDexAnnotationFloat: break; 995 case kDexAnnotationDouble: break; 996 case kDexAnnotationString: break; 997 case kDexAnnotationType: break; 998 case kDexAnnotationMethod: break; 999 case kDexAnnotationField: break; 1000 case kDexAnnotationEnum: break; 1001 1002 case kDexAnnotationArray: 1003 /* encoded_array format */ 1004 { 1005 u4 size = readUleb128(&ptr); 1006 while (size--) { 1007 if (!skipAnnotationValue(clazz, &ptr)) 1008 return false; 1009 } 1010 } 1011 width = 0; 1012 break; 1013 case kDexAnnotationAnnotation: 1014 /* encoded_annotation format */ 1015 if (!skipEncodedAnnotation(clazz, &ptr)) 1016 return false; 1017 width = 0; 1018 break; 1019 case kDexAnnotationBoolean: 1020 case kDexAnnotationNull: 1021 width = 0; 1022 break; 1023 default: 1024 ALOGE("Bad annotation element value byte 0x%02x", valueType); 1025 assert(false); 1026 return false; 1027 } 1028 1029 ptr += width; 1030 1031 *pPtr = ptr; 1032 return true; 1033 } 1034 1035 /* 1036 * Skip past an encoded annotation. Mainly useful for annotations embedded 1037 * in other annotations. 1038 */ 1039 static bool skipEncodedAnnotation(const ClassObject* clazz, const u1** pPtr) 1040 { 1041 const u1* ptr; 1042 u4 size; 1043 1044 ptr = *pPtr; 1045 (void) readUleb128(&ptr); 1046 size = readUleb128(&ptr); 1047 1048 /* 1049 * "ptr" points to a byte stream with "size" occurrences of 1050 * annotation_element. 1051 */ 1052 while (size--) { 1053 (void) readUleb128(&ptr); 1054 1055 if (!skipAnnotationValue(clazz, &ptr)) 1056 return false; 1057 } 1058 1059 *pPtr = ptr; 1060 return true; 1061 } 1062 1063 1064 /* 1065 * Compare the name of the class in the DEX file to the supplied descriptor. 1066 * Return value is equivalent to strcmp. 1067 */ 1068 static int compareClassDescriptor(DexFile* pDexFile, u4 typeIdx, 1069 const char* descriptor) 1070 { 1071 const char* str = dexStringByTypeIdx(pDexFile, typeIdx); 1072 1073 return strcmp(str, descriptor); 1074 } 1075 1076 /* 1077 * Search through the annotation set for an annotation with a matching 1078 * descriptor. 1079 * 1080 * Comparing the string descriptor is slower than comparing an integer class 1081 * index. If annotation lists are expected to be long, we could look up 1082 * the class' index by name from the DEX file, rather than doing a class 1083 * lookup and string compare on each entry. (Note the index will be 1084 * different for each DEX file, so we can't cache annotation class indices 1085 * globally.) 1086 */ 1087 static const DexAnnotationItem* searchAnnotationSet(const ClassObject* clazz, 1088 const DexAnnotationSetItem* pAnnoSet, const char* descriptor, 1089 int visibility) 1090 { 1091 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 1092 const DexAnnotationItem* result = NULL; 1093 u4 typeIdx; 1094 int i; 1095 1096 //printf("##### searchAnnotationSet %s %d\n", descriptor, visibility); 1097 1098 for (i = 0; i < (int) pAnnoSet->size; i++) { 1099 const DexAnnotationItem* pAnnoItem; 1100 1101 pAnnoItem = dexGetAnnotationItem(pDexFile, pAnnoSet, i); 1102 if (pAnnoItem->visibility != visibility) 1103 continue; 1104 const u1* ptr = pAnnoItem->annotation; 1105 typeIdx = readUleb128(&ptr); 1106 1107 if (compareClassDescriptor(pDexFile, typeIdx, descriptor) == 0) { 1108 //printf("##### match on %x/%p at %d\n", typeIdx, pDexFile, i); 1109 result = pAnnoItem; 1110 break; 1111 } 1112 } 1113 1114 return result; 1115 } 1116 1117 /* 1118 * Find an annotation value in the annotation_item whose name matches "name". 1119 * A pointer to the annotation_value is returned, or NULL if it's not found. 1120 */ 1121 static const u1* searchEncodedAnnotation(const ClassObject* clazz, 1122 const u1* ptr, const char* name) 1123 { 1124 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 1125 u4 typeIdx, size; 1126 1127 typeIdx = readUleb128(&ptr); 1128 size = readUleb128(&ptr); 1129 //printf("##### searching ptr=%p type=%u size=%u\n", ptr, typeIdx, size); 1130 1131 while (size--) { 1132 u4 elementNameIdx; 1133 const char* elemName; 1134 1135 elementNameIdx = readUleb128(&ptr); 1136 elemName = dexStringById(pDexFile, elementNameIdx); 1137 if (strcmp(name, elemName) == 0) { 1138 //printf("##### item match on %s\n", name); 1139 return ptr; /* points to start of value */ 1140 } 1141 1142 skipAnnotationValue(clazz, &ptr); 1143 } 1144 1145 //printf("##### no item match on %s\n", name); 1146 return NULL; 1147 } 1148 1149 #define GAV_FAILED ((Object*) 0x10000001) 1150 1151 /* 1152 * Extract an encoded annotation value from the field specified by "annoName". 1153 * 1154 * "expectedType" is an annotation value type, e.g. kDexAnnotationString. 1155 * "debugAnnoName" is only used in debug messages. 1156 * 1157 * Returns GAV_FAILED on failure. If an allocation failed, an exception 1158 * will be raised. 1159 */ 1160 static Object* getAnnotationValue(const ClassObject* clazz, 1161 const DexAnnotationItem* pAnnoItem, const char* annoName, 1162 int expectedType, const char* debugAnnoName) 1163 { 1164 const u1* ptr; 1165 AnnotationValue avalue; 1166 1167 /* find the annotation */ 1168 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, annoName); 1169 if (ptr == NULL) { 1170 ALOGW("%s annotation lacks '%s' member", debugAnnoName, annoName); 1171 return GAV_FAILED; 1172 } 1173 1174 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) 1175 return GAV_FAILED; 1176 1177 /* make sure it has the expected format */ 1178 if (avalue.type != expectedType) { 1179 ALOGW("%s %s has wrong type (0x%02x, expected 0x%02x)", 1180 debugAnnoName, annoName, avalue.type, expectedType); 1181 return GAV_FAILED; 1182 } 1183 1184 return (Object*)avalue.value.l; 1185 } 1186 1187 1188 /* 1189 * Find the Signature attribute and extract its value. (Signatures can 1190 * be found in annotations on classes, constructors, methods, and fields.) 1191 * 1192 * Caller must call dvmReleaseTrackedAlloc(). 1193 * 1194 * Returns NULL if not found. On memory alloc failure, returns NULL with an 1195 * exception raised. 1196 */ 1197 static ArrayObject* getSignatureValue(const ClassObject* clazz, 1198 const DexAnnotationSetItem* pAnnoSet) 1199 { 1200 const DexAnnotationItem* pAnnoItem; 1201 Object* obj; 1202 1203 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrSignature, 1204 kDexVisibilitySystem); 1205 if (pAnnoItem == NULL) 1206 return NULL; 1207 1208 /* 1209 * The Signature annotation has one member, "String value". 1210 */ 1211 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationArray, 1212 "Signature"); 1213 if (obj == GAV_FAILED) 1214 return NULL; 1215 assert(obj->clazz == gDvm.classJavaLangObjectArray); 1216 1217 return (ArrayObject*)obj; 1218 } 1219 1220 1221 /* 1222 * =========================================================================== 1223 * Class 1224 * =========================================================================== 1225 */ 1226 1227 /* 1228 * Find the DexAnnotationSetItem for this class. 1229 */ 1230 static const DexAnnotationSetItem* findAnnotationSetForClass( 1231 const ClassObject* clazz) 1232 { 1233 DexFile* pDexFile; 1234 const DexAnnotationsDirectoryItem* pAnnoDir; 1235 1236 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */ 1237 return NULL; 1238 1239 pDexFile = clazz->pDvmDex->pDexFile; 1240 pAnnoDir = getAnnoDirectory(pDexFile, clazz); 1241 if (pAnnoDir != NULL) 1242 return dexGetClassAnnotationSet(pDexFile, pAnnoDir); 1243 else 1244 return NULL; 1245 } 1246 1247 /* 1248 * Return an array of Annotation objects for the class. Returns an empty 1249 * array if there are no annotations. 1250 * 1251 * Caller must call dvmReleaseTrackedAlloc(). 1252 * 1253 * On allocation failure, this returns NULL with an exception raised. 1254 */ 1255 ArrayObject* dvmGetClassAnnotations(const ClassObject* clazz) 1256 { 1257 ArrayObject* annoArray; 1258 const DexAnnotationSetItem* pAnnoSet = NULL; 1259 1260 pAnnoSet = findAnnotationSetForClass(clazz); 1261 if (pAnnoSet == NULL) { 1262 /* no annotations for anything in class, or no class annotations */ 1263 annoArray = emptyAnnoArray(); 1264 } else { 1265 annoArray = processAnnotationSet(clazz, pAnnoSet, 1266 kDexVisibilityRuntime); 1267 } 1268 1269 return annoArray; 1270 } 1271 1272 /* 1273 * Returns the annotation or NULL if it doesn't exist. 1274 */ 1275 Object* dvmGetClassAnnotation(const ClassObject* clazz, 1276 const ClassObject* annotationClazz) 1277 { 1278 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForClass(clazz); 1279 if (pAnnoSet == NULL) { 1280 return NULL; 1281 } 1282 return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet, 1283 kDexVisibilityRuntime, annotationClazz); 1284 } 1285 1286 /* 1287 * Returns true if the annotation exists. 1288 */ 1289 bool dvmIsClassAnnotationPresent(const ClassObject* clazz, 1290 const ClassObject* annotationClazz) 1291 { 1292 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForClass(clazz); 1293 if (pAnnoSet == NULL) { 1294 return NULL; 1295 } 1296 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet( 1297 clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz); 1298 return (pAnnoItem != NULL); 1299 } 1300 1301 /* 1302 * Retrieve the Signature annotation, if any. Returns NULL if no signature 1303 * exists. 1304 * 1305 * Caller must call dvmReleaseTrackedAlloc(). 1306 */ 1307 ArrayObject* dvmGetClassSignatureAnnotation(const ClassObject* clazz) 1308 { 1309 ArrayObject* signature = NULL; 1310 const DexAnnotationSetItem* pAnnoSet; 1311 1312 pAnnoSet = findAnnotationSetForClass(clazz); 1313 if (pAnnoSet != NULL) 1314 signature = getSignatureValue(clazz, pAnnoSet); 1315 1316 return signature; 1317 } 1318 1319 /* 1320 * Get the EnclosingMethod attribute from an annotation. Returns a Method 1321 * object, or NULL. 1322 * 1323 * Caller must call dvmReleaseTrackedAlloc(). 1324 */ 1325 Object* dvmGetEnclosingMethod(const ClassObject* clazz) 1326 { 1327 const DexAnnotationItem* pAnnoItem; 1328 const DexAnnotationSetItem* pAnnoSet; 1329 Object* obj; 1330 1331 pAnnoSet = findAnnotationSetForClass(clazz); 1332 if (pAnnoSet == NULL) 1333 return NULL; 1334 1335 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingMethod, 1336 kDexVisibilitySystem); 1337 if (pAnnoItem == NULL) 1338 return NULL; 1339 1340 /* 1341 * The EnclosingMethod annotation has one member, "Method value". 1342 */ 1343 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationMethod, 1344 "EnclosingMethod"); 1345 if (obj == GAV_FAILED) 1346 return NULL; 1347 assert(obj->clazz == gDvm.classJavaLangReflectConstructor || 1348 obj->clazz == gDvm.classJavaLangReflectMethod); 1349 1350 return obj; 1351 } 1352 1353 /* 1354 * Find a class' enclosing class. We return what we find in the 1355 * EnclosingClass attribute. 1356 * 1357 * Returns a Class object, or NULL. 1358 * 1359 * Caller must call dvmReleaseTrackedAlloc(). 1360 */ 1361 ClassObject* dvmGetDeclaringClass(const ClassObject* clazz) 1362 { 1363 const DexAnnotationItem* pAnnoItem; 1364 const DexAnnotationSetItem* pAnnoSet; 1365 Object* obj; 1366 1367 pAnnoSet = findAnnotationSetForClass(clazz); 1368 if (pAnnoSet == NULL) 1369 return NULL; 1370 1371 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingClass, 1372 kDexVisibilitySystem); 1373 if (pAnnoItem == NULL) 1374 return NULL; 1375 1376 /* 1377 * The EnclosingClass annotation has one member, "Class value". 1378 */ 1379 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationType, 1380 "EnclosingClass"); 1381 if (obj == GAV_FAILED) 1382 return NULL; 1383 1384 assert(dvmIsClassObject(obj)); 1385 return (ClassObject*)obj; 1386 } 1387 1388 /* 1389 * Find a class' enclosing class. We first search for an EnclosingClass 1390 * attribute, and if that's not found we look for an EnclosingMethod. 1391 * 1392 * Returns a Class object, or NULL. 1393 * 1394 * Caller must call dvmReleaseTrackedAlloc(). 1395 */ 1396 ClassObject* dvmGetEnclosingClass(const ClassObject* clazz) 1397 { 1398 const DexAnnotationItem* pAnnoItem; 1399 const DexAnnotationSetItem* pAnnoSet; 1400 Object* obj; 1401 1402 pAnnoSet = findAnnotationSetForClass(clazz); 1403 if (pAnnoSet == NULL) 1404 return NULL; 1405 1406 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingClass, 1407 kDexVisibilitySystem); 1408 if (pAnnoItem != NULL) { 1409 /* 1410 * The EnclosingClass annotation has one member, "Class value". 1411 */ 1412 obj = getAnnotationValue(clazz, pAnnoItem, "value", kDexAnnotationType, 1413 "EnclosingClass"); 1414 if (obj != GAV_FAILED) { 1415 assert(dvmIsClassObject(obj)); 1416 return (ClassObject*)obj; 1417 } 1418 } 1419 1420 /* 1421 * That didn't work. Look for an EnclosingMethod. 1422 * 1423 * We could create a java.lang.reflect.Method object and extract the 1424 * declaringClass from it, but that's more work than we want to do. 1425 * Instead, we find the "value" item and parse the index out ourselves. 1426 */ 1427 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrEnclosingMethod, 1428 kDexVisibilitySystem); 1429 if (pAnnoItem == NULL) 1430 return NULL; 1431 1432 /* find the value member */ 1433 const u1* ptr; 1434 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "value"); 1435 if (ptr == NULL) { 1436 ALOGW("EnclosingMethod annotation lacks 'value' member"); 1437 return NULL; 1438 } 1439 1440 /* parse it, verify the type */ 1441 AnnotationValue avalue; 1442 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllRaw)) { 1443 ALOGW("EnclosingMethod parse failed"); 1444 return NULL; 1445 } 1446 if (avalue.type != kDexAnnotationMethod) { 1447 ALOGW("EnclosingMethod value has wrong type (0x%02x, expected 0x%02x)", 1448 avalue.type, kDexAnnotationMethod); 1449 return NULL; 1450 } 1451 1452 /* pull out the method index and resolve the method */ 1453 Method* meth = resolveAmbiguousMethod(clazz, avalue.value.i); 1454 if (meth == NULL) 1455 return NULL; 1456 1457 ClassObject* methClazz = meth->clazz; 1458 dvmAddTrackedAlloc((Object*) methClazz, NULL); // balance the Release 1459 return methClazz; 1460 } 1461 1462 /* 1463 * Get the EnclosingClass attribute from an annotation. If found, returns 1464 * "true". A String with the original name of the class and the original 1465 * access flags are returned through the arguments. (The name will be NULL 1466 * for an anonymous inner class.) 1467 * 1468 * Caller must call dvmReleaseTrackedAlloc(). 1469 */ 1470 bool dvmGetInnerClass(const ClassObject* clazz, StringObject** pName, 1471 int* pAccessFlags) 1472 { 1473 const DexAnnotationItem* pAnnoItem; 1474 const DexAnnotationSetItem* pAnnoSet; 1475 1476 pAnnoSet = findAnnotationSetForClass(clazz); 1477 if (pAnnoSet == NULL) 1478 return false; 1479 1480 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrInnerClass, 1481 kDexVisibilitySystem); 1482 if (pAnnoItem == NULL) 1483 return false; 1484 1485 /* 1486 * The InnerClass annotation has two members, "String name" and 1487 * "int accessFlags". We don't want to get the access flags as an 1488 * Integer, so we process that as a simple value. 1489 */ 1490 const u1* ptr; 1491 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "name"); 1492 if (ptr == NULL) { 1493 ALOGW("InnerClass annotation lacks 'name' member"); 1494 return false; 1495 } 1496 1497 /* parse it into an Object */ 1498 AnnotationValue avalue; 1499 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) { 1500 ALOGD("processAnnotationValue failed on InnerClass member 'name'"); 1501 return false; 1502 } 1503 1504 /* make sure it has the expected format */ 1505 if (avalue.type != kDexAnnotationNull && 1506 avalue.type != kDexAnnotationString) 1507 { 1508 ALOGW("InnerClass name has bad type (0x%02x, expected STRING or NULL)", 1509 avalue.type); 1510 return false; 1511 } 1512 1513 *pName = (StringObject*) avalue.value.l; 1514 assert(*pName == NULL || (*pName)->clazz == gDvm.classJavaLangString); 1515 1516 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "accessFlags"); 1517 if (ptr == NULL) { 1518 ALOGW("InnerClass annotation lacks 'accessFlags' member"); 1519 return false; 1520 } 1521 1522 /* parse it, verify the type */ 1523 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllRaw)) { 1524 ALOGW("InnerClass accessFlags parse failed"); 1525 return false; 1526 } 1527 if (avalue.type != kDexAnnotationInt) { 1528 ALOGW("InnerClass value has wrong type (0x%02x, expected 0x%02x)", 1529 avalue.type, kDexAnnotationInt); 1530 return false; 1531 } 1532 1533 *pAccessFlags = avalue.value.i; 1534 1535 return true; 1536 } 1537 1538 /* 1539 * Extract an array of Class objects from the MemberClasses annotation 1540 * for this class. 1541 * 1542 * Caller must call dvmReleaseTrackedAlloc(). 1543 * 1544 * Returns NULL if we don't find any member classes. 1545 */ 1546 ArrayObject* dvmGetDeclaredClasses(const ClassObject* clazz) 1547 { 1548 const DexAnnotationSetItem* pAnnoSet; 1549 const DexAnnotationItem* pAnnoItem; 1550 Object* obj; 1551 1552 pAnnoSet = findAnnotationSetForClass(clazz); 1553 if (pAnnoSet == NULL) 1554 return NULL; 1555 1556 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrMemberClasses, 1557 kDexVisibilitySystem); 1558 if (pAnnoItem == NULL) 1559 return NULL; 1560 1561 /* 1562 * The MemberClasses annotation has one member, "Class[] value". 1563 */ 1564 obj = getAnnotationValue(clazz, pAnnoItem, "value", 1565 kDexAnnotationArray, "MemberClasses"); 1566 if (obj == GAV_FAILED) 1567 return NULL; 1568 assert(dvmIsArray((ArrayObject*)obj)); 1569 obj = convertReturnType(obj, gDvm.classJavaLangClassArray); 1570 return (ArrayObject*)obj; 1571 } 1572 1573 1574 /* 1575 * =========================================================================== 1576 * Method (and Constructor) 1577 * =========================================================================== 1578 */ 1579 1580 /* 1581 * Compare the attributes (class name, method name, method signature) of 1582 * the specified method to "method". 1583 */ 1584 static int compareMethodStr(DexFile* pDexFile, u4 methodIdx, 1585 const Method* method) 1586 { 1587 const DexMethodId* pMethodId = dexGetMethodId(pDexFile, methodIdx); 1588 const char* str = dexStringByTypeIdx(pDexFile, pMethodId->classIdx); 1589 int result = strcmp(str, method->clazz->descriptor); 1590 1591 if (result == 0) { 1592 str = dexStringById(pDexFile, pMethodId->nameIdx); 1593 result = strcmp(str, method->name); 1594 if (result == 0) { 1595 DexProto proto; 1596 dexProtoSetFromMethodId(&proto, pDexFile, pMethodId); 1597 result = dexProtoCompare(&proto, &method->prototype); 1598 } 1599 } 1600 1601 return result; 1602 } 1603 1604 /* 1605 * Given a method, determine the method's index. 1606 * 1607 * We could simply store this in the Method*, but that would cost 4 bytes 1608 * per method. Instead we plow through the DEX data. 1609 * 1610 * We have two choices: look through the class method data, or look through 1611 * the global method_ids table. The former is awkward because the method 1612 * could have been defined in a superclass or interface. The latter works 1613 * out reasonably well because it's in sorted order, though we're still left 1614 * doing a fair number of string comparisons. 1615 */ 1616 static u4 getMethodIdx(const Method* method) 1617 { 1618 DexFile* pDexFile = method->clazz->pDvmDex->pDexFile; 1619 u4 hi = pDexFile->pHeader->methodIdsSize -1; 1620 u4 lo = 0; 1621 u4 cur; 1622 1623 while (hi >= lo) { 1624 int cmp; 1625 cur = (lo + hi) / 2; 1626 1627 cmp = compareMethodStr(pDexFile, cur, method); 1628 if (cmp < 0) { 1629 lo = cur + 1; 1630 } else if (cmp > 0) { 1631 hi = cur - 1; 1632 } else { 1633 break; 1634 } 1635 } 1636 1637 if (hi < lo) { 1638 /* this should be impossible -- the method came out of this DEX */ 1639 char* desc = dexProtoCopyMethodDescriptor(&method->prototype); 1640 ALOGE("Unable to find method %s.%s %s in DEX file!", 1641 method->clazz->descriptor, method->name, desc); 1642 free(desc); 1643 dvmAbort(); 1644 } 1645 1646 return cur; 1647 } 1648 1649 /* 1650 * Find the DexAnnotationSetItem for this method. 1651 * 1652 * Returns NULL if none found. 1653 */ 1654 static const DexAnnotationSetItem* findAnnotationSetForMethod( 1655 const Method* method) 1656 { 1657 ClassObject* clazz = method->clazz; 1658 DexFile* pDexFile; 1659 const DexAnnotationsDirectoryItem* pAnnoDir; 1660 const DexMethodAnnotationsItem* pMethodList; 1661 const DexAnnotationSetItem* pAnnoSet = NULL; 1662 1663 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */ 1664 return NULL; 1665 pDexFile = clazz->pDvmDex->pDexFile; 1666 1667 pAnnoDir = getAnnoDirectory(pDexFile, clazz); 1668 if (pAnnoDir != NULL) { 1669 pMethodList = dexGetMethodAnnotations(pDexFile, pAnnoDir); 1670 if (pMethodList != NULL) { 1671 /* 1672 * Run through the list and find a matching method. We compare the 1673 * method ref indices in the annotation list with the method's DEX 1674 * method_idx value. 1675 * 1676 * TODO: use a binary search for long lists 1677 * 1678 * Alternate approach: for each entry in the annotations list, 1679 * find the method definition in the DEX file and perform string 1680 * comparisons on class name, method name, and signature. 1681 */ 1682 u4 methodIdx = getMethodIdx(method); 1683 u4 count = dexGetMethodAnnotationsSize(pDexFile, pAnnoDir); 1684 u4 idx; 1685 1686 for (idx = 0; idx < count; idx++) { 1687 if (pMethodList[idx].methodIdx == methodIdx) { 1688 /* found! */ 1689 pAnnoSet = dexGetMethodAnnotationSetItem(pDexFile, 1690 &pMethodList[idx]); 1691 break; 1692 } 1693 } 1694 } 1695 } 1696 1697 return pAnnoSet; 1698 } 1699 1700 /* 1701 * Return an array of Annotation objects for the method. Returns an empty 1702 * array if there are no annotations. 1703 * 1704 * Caller must call dvmReleaseTrackedAlloc(). 1705 * 1706 * On allocation failure, this returns NULL with an exception raised. 1707 */ 1708 ArrayObject* dvmGetMethodAnnotations(const Method* method) 1709 { 1710 ClassObject* clazz = method->clazz; 1711 const DexAnnotationSetItem* pAnnoSet; 1712 ArrayObject* annoArray = NULL; 1713 1714 pAnnoSet = findAnnotationSetForMethod(method); 1715 if (pAnnoSet == NULL) { 1716 /* no matching annotations found */ 1717 annoArray = emptyAnnoArray(); 1718 } else { 1719 annoArray = processAnnotationSet(clazz, pAnnoSet,kDexVisibilityRuntime); 1720 } 1721 1722 return annoArray; 1723 } 1724 1725 /* 1726 * Returns the annotation or NULL if it doesn't exist. 1727 */ 1728 Object* dvmGetMethodAnnotation(const ClassObject* clazz, const Method* method, 1729 const ClassObject* annotationClazz) 1730 { 1731 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForMethod(method); 1732 if (pAnnoSet == NULL) { 1733 return NULL; 1734 } 1735 return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet, 1736 kDexVisibilityRuntime, annotationClazz); 1737 } 1738 1739 /* 1740 * Returns true if the annotation exists. 1741 */ 1742 bool dvmIsMethodAnnotationPresent(const ClassObject* clazz, 1743 const Method* method, const ClassObject* annotationClazz) 1744 { 1745 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForMethod(method); 1746 if (pAnnoSet == NULL) { 1747 return NULL; 1748 } 1749 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet( 1750 clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz); 1751 return (pAnnoItem != NULL); 1752 } 1753 1754 /* 1755 * Retrieve the Signature annotation, if any. Returns NULL if no signature 1756 * exists. 1757 * 1758 * Caller must call dvmReleaseTrackedAlloc(). 1759 */ 1760 ArrayObject* dvmGetMethodSignatureAnnotation(const Method* method) 1761 { 1762 ClassObject* clazz = method->clazz; 1763 const DexAnnotationSetItem* pAnnoSet; 1764 ArrayObject* signature = NULL; 1765 1766 pAnnoSet = findAnnotationSetForMethod(method); 1767 if (pAnnoSet != NULL) 1768 signature = getSignatureValue(clazz, pAnnoSet); 1769 1770 return signature; 1771 } 1772 1773 /* 1774 * Extract an array of exception classes from the "system" annotation list 1775 * for this method. 1776 * 1777 * Caller must call dvmReleaseTrackedAlloc(). 1778 * 1779 * Returns NULL if we don't find any exceptions for this method. 1780 */ 1781 ArrayObject* dvmGetMethodThrows(const Method* method) 1782 { 1783 ClassObject* clazz = method->clazz; 1784 const DexAnnotationSetItem* pAnnoSet; 1785 const DexAnnotationItem* pAnnoItem; 1786 1787 /* find the set for this method */ 1788 pAnnoSet = findAnnotationSetForMethod(method); 1789 if (pAnnoSet == NULL) 1790 return NULL; /* nothing for this method */ 1791 1792 /* find the "Throws" annotation, if any */ 1793 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrThrows, 1794 kDexVisibilitySystem); 1795 if (pAnnoItem == NULL) 1796 return NULL; /* no Throws */ 1797 1798 /* 1799 * The Throws annotation has one member, "Class[] value". 1800 */ 1801 Object* obj = getAnnotationValue(clazz, pAnnoItem, "value", 1802 kDexAnnotationArray, "Throws"); 1803 if (obj == GAV_FAILED) 1804 return NULL; 1805 assert(dvmIsArray((ArrayObject*)obj)); 1806 obj = convertReturnType(obj, gDvm.classJavaLangClassArray); 1807 return (ArrayObject*)obj; 1808 } 1809 1810 /* 1811 * Given an Annotation's method, find the default value, if any. 1812 * 1813 * If this is a CLASS annotation, and we can't find a match for the 1814 * default class value, we need to throw a TypeNotPresentException. 1815 * 1816 * Caller must call dvmReleaseTrackedAlloc(). 1817 */ 1818 Object* dvmGetAnnotationDefaultValue(const Method* method) 1819 { 1820 const ClassObject* clazz = method->clazz; 1821 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 1822 const DexAnnotationsDirectoryItem* pAnnoDir; 1823 const DexAnnotationSetItem* pAnnoSet = NULL; 1824 1825 /* 1826 * The method's declaring class (the annotation) will have an 1827 * AnnotationDefault "system" annotation associated with it if any 1828 * of its methods have default values. Start by finding the 1829 * DexAnnotationItem associated with the class. 1830 */ 1831 pAnnoDir = getAnnoDirectory(pDexFile, clazz); 1832 if (pAnnoDir != NULL) 1833 pAnnoSet = dexGetClassAnnotationSet(pDexFile, pAnnoDir); 1834 if (pAnnoSet == NULL) { 1835 /* no annotations for anything in class, or no class annotations */ 1836 return NULL; 1837 } 1838 1839 /* find the "AnnotationDefault" annotation, if any */ 1840 const DexAnnotationItem* pAnnoItem; 1841 pAnnoItem = searchAnnotationSet(clazz, pAnnoSet, kDescrAnnotationDefault, 1842 kDexVisibilitySystem); 1843 if (pAnnoItem == NULL) { 1844 /* no default values for any member in this annotation */ 1845 //printf("##### no default annotations for %s.%s\n", 1846 // method->clazz->descriptor, method->name); 1847 return NULL; 1848 } 1849 1850 /* 1851 * The AnnotationDefault annotation has one member, "Annotation value". 1852 * We need to pull that out. 1853 */ 1854 const u1* ptr; 1855 ptr = searchEncodedAnnotation(clazz, pAnnoItem->annotation, "value"); 1856 if (ptr == NULL) { 1857 ALOGW("AnnotationDefault annotation lacks 'value'"); 1858 return NULL; 1859 } 1860 if ((*ptr & kDexAnnotationValueTypeMask) != kDexAnnotationAnnotation) { 1861 ALOGW("AnnotationDefault value has wrong type (0x%02x)", 1862 *ptr & kDexAnnotationValueTypeMask); 1863 return NULL; 1864 } 1865 1866 /* 1867 * The value_type byte for VALUE_ANNOTATION is followed by 1868 * encoded_annotation data. We want to scan through it to find an 1869 * entry whose name matches our method name. 1870 */ 1871 ptr++; 1872 ptr = searchEncodedAnnotation(clazz, ptr, method->name); 1873 if (ptr == NULL) 1874 return NULL; /* no default annotation for this method */ 1875 1876 /* got it, pull it out */ 1877 AnnotationValue avalue; 1878 if (!processAnnotationValue(clazz, &ptr, &avalue, kAllObjects)) { 1879 ALOGD("processAnnotationValue failed on default for '%s'", 1880 method->name); 1881 return NULL; 1882 } 1883 1884 /* convert the return type, if necessary */ 1885 ClassObject* methodReturn = dvmGetBoxedReturnType(method); 1886 Object* obj = (Object*)avalue.value.l; 1887 obj = convertReturnType(obj, methodReturn); 1888 1889 return obj; 1890 } 1891 1892 1893 /* 1894 * =========================================================================== 1895 * Field 1896 * =========================================================================== 1897 */ 1898 1899 /* 1900 * Compare the attributes (class name, field name, field signature) of 1901 * the specified field to "field". 1902 */ 1903 static int compareFieldStr(DexFile* pDexFile, u4 idx, const Field* field) 1904 { 1905 const DexFieldId* pFieldId = dexGetFieldId(pDexFile, idx); 1906 const char* str = dexStringByTypeIdx(pDexFile, pFieldId->classIdx); 1907 int result = strcmp(str, field->clazz->descriptor); 1908 1909 if (result == 0) { 1910 str = dexStringById(pDexFile, pFieldId->nameIdx); 1911 result = strcmp(str, field->name); 1912 if (result == 0) { 1913 str = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx); 1914 result = strcmp(str, field->signature); 1915 } 1916 } 1917 1918 return result; 1919 } 1920 1921 /* 1922 * Given a field, determine the field's index. 1923 * 1924 * This has the same tradeoffs as getMethodIdx. 1925 */ 1926 static u4 getFieldIdx(const Field* field) 1927 { 1928 DexFile* pDexFile = field->clazz->pDvmDex->pDexFile; 1929 u4 hi = pDexFile->pHeader->fieldIdsSize -1; 1930 u4 lo = 0; 1931 u4 cur; 1932 1933 while (hi >= lo) { 1934 int cmp; 1935 cur = (lo + hi) / 2; 1936 1937 cmp = compareFieldStr(pDexFile, cur, field); 1938 if (cmp < 0) { 1939 lo = cur + 1; 1940 } else if (cmp > 0) { 1941 hi = cur - 1; 1942 } else { 1943 break; 1944 } 1945 } 1946 1947 if (hi < lo) { 1948 /* this should be impossible -- the field came out of this DEX */ 1949 ALOGE("Unable to find field %s.%s %s in DEX file!", 1950 field->clazz->descriptor, field->name, field->signature); 1951 dvmAbort(); 1952 } 1953 1954 return cur; 1955 } 1956 1957 /* 1958 * Find the DexAnnotationSetItem for this field. 1959 * 1960 * Returns NULL if none found. 1961 */ 1962 static const DexAnnotationSetItem* findAnnotationSetForField(const Field* field) 1963 { 1964 ClassObject* clazz = field->clazz; 1965 DvmDex* pDvmDex = clazz->pDvmDex; 1966 if (pDvmDex == NULL) { 1967 return NULL; 1968 } 1969 1970 DexFile* pDexFile = pDvmDex->pDexFile; 1971 1972 const DexAnnotationsDirectoryItem* pAnnoDir = getAnnoDirectory(pDexFile, clazz); 1973 if (pAnnoDir == NULL) { 1974 return NULL; 1975 } 1976 1977 const DexFieldAnnotationsItem* pFieldList = dexGetFieldAnnotations(pDexFile, pAnnoDir); 1978 if (pFieldList == NULL) { 1979 return NULL; 1980 } 1981 1982 /* 1983 * Run through the list and find a matching field. We compare the 1984 * field ref indices in the annotation list with the field's DEX 1985 * field_idx value. 1986 * 1987 * TODO: use a binary search for long lists 1988 * 1989 * Alternate approach: for each entry in the annotations list, 1990 * find the field definition in the DEX file and perform string 1991 * comparisons on class name, field name, and signature. 1992 */ 1993 u4 fieldIdx = getFieldIdx(field); 1994 u4 count = dexGetFieldAnnotationsSize(pDexFile, pAnnoDir); 1995 u4 idx; 1996 1997 for (idx = 0; idx < count; idx++) { 1998 if (pFieldList[idx].fieldIdx == fieldIdx) { 1999 /* found! */ 2000 return dexGetFieldAnnotationSetItem(pDexFile, &pFieldList[idx]); 2001 } 2002 } 2003 2004 return NULL; 2005 } 2006 2007 /* 2008 * Return an array of Annotation objects for the field. Returns an empty 2009 * array if there are no annotations. 2010 * 2011 * Caller must call dvmReleaseTrackedAlloc(). 2012 * 2013 * On allocation failure, this returns NULL with an exception raised. 2014 */ 2015 ArrayObject* dvmGetFieldAnnotations(const Field* field) 2016 { 2017 ClassObject* clazz = field->clazz; 2018 ArrayObject* annoArray = NULL; 2019 const DexAnnotationSetItem* pAnnoSet = NULL; 2020 2021 pAnnoSet = findAnnotationSetForField(field); 2022 if (pAnnoSet == NULL) { 2023 /* no matching annotations found */ 2024 annoArray = emptyAnnoArray(); 2025 } else { 2026 annoArray = processAnnotationSet(clazz, pAnnoSet, 2027 kDexVisibilityRuntime); 2028 } 2029 2030 return annoArray; 2031 } 2032 2033 /* 2034 * Returns the annotation or NULL if it doesn't exist. 2035 */ 2036 Object* dvmGetFieldAnnotation(const ClassObject* clazz, const Field* field, 2037 const ClassObject* annotationClazz) 2038 { 2039 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForField(field); 2040 if (pAnnoSet == NULL) { 2041 return NULL; 2042 } 2043 return getAnnotationObjectFromAnnotationSet(clazz, pAnnoSet, 2044 kDexVisibilityRuntime, annotationClazz); 2045 } 2046 2047 /* 2048 * Returns true if the annotation exists. 2049 */ 2050 bool dvmIsFieldAnnotationPresent(const ClassObject* clazz, 2051 const Field* field, const ClassObject* annotationClazz) 2052 { 2053 const DexAnnotationSetItem* pAnnoSet = findAnnotationSetForField(field); 2054 if (pAnnoSet == NULL) { 2055 return NULL; 2056 } 2057 const DexAnnotationItem* pAnnoItem = getAnnotationItemFromAnnotationSet( 2058 clazz, pAnnoSet, kDexVisibilityRuntime, annotationClazz); 2059 return (pAnnoItem != NULL); 2060 } 2061 2062 /* 2063 * Retrieve the Signature annotation, if any. Returns NULL if no signature 2064 * exists. 2065 * 2066 * Caller must call dvmReleaseTrackedAlloc(). 2067 */ 2068 ArrayObject* dvmGetFieldSignatureAnnotation(const Field* field) 2069 { 2070 ClassObject* clazz = field->clazz; 2071 const DexAnnotationSetItem* pAnnoSet; 2072 ArrayObject* signature = NULL; 2073 2074 pAnnoSet = findAnnotationSetForField(field); 2075 if (pAnnoSet != NULL) 2076 signature = getSignatureValue(clazz, pAnnoSet); 2077 2078 return signature; 2079 } 2080 2081 2082 /* 2083 * =========================================================================== 2084 * Parameter 2085 * =========================================================================== 2086 */ 2087 2088 /* 2089 * We have an annotation_set_ref_list, which is essentially a list of 2090 * entries that we pass to processAnnotationSet(). 2091 * 2092 * The returned object must be released with dvmReleaseTrackedAlloc. 2093 */ 2094 static ArrayObject* processAnnotationSetRefList(const ClassObject* clazz, 2095 const DexAnnotationSetRefList* pAnnoSetList, u4 count) 2096 { 2097 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 2098 ArrayObject* annoArrayArray = NULL; 2099 u4 idx; 2100 2101 /* allocate an array of Annotation arrays to hold results */ 2102 annoArrayArray = dvmAllocArrayByClass( 2103 gDvm.classJavaLangAnnotationAnnotationArrayArray, count, ALLOC_DEFAULT); 2104 if (annoArrayArray == NULL) { 2105 ALOGW("annotation set ref array alloc failed"); 2106 goto bail; 2107 } 2108 2109 for (idx = 0; idx < count; idx++) { 2110 Thread* self = dvmThreadSelf(); 2111 const DexAnnotationSetRefItem* pItem; 2112 const DexAnnotationSetItem* pAnnoSet; 2113 Object *annoSet; 2114 DexAnnotationSetItem emptySet; 2115 emptySet.size = 0; 2116 2117 pItem = dexGetParameterAnnotationSetRef(pAnnoSetList, idx); 2118 pAnnoSet = dexGetSetRefItemItem(pDexFile, pItem); 2119 if (pAnnoSet == NULL) { 2120 pAnnoSet = &emptySet; 2121 } 2122 2123 annoSet = (Object *)processAnnotationSet(clazz, 2124 pAnnoSet, 2125 kDexVisibilityRuntime); 2126 if (annoSet == NULL) { 2127 ALOGW("processAnnotationSet failed"); 2128 annoArrayArray = NULL; 2129 goto bail; 2130 } 2131 dvmSetObjectArrayElement(annoArrayArray, idx, annoSet); 2132 dvmReleaseTrackedAlloc((Object*) annoSet, self); 2133 } 2134 2135 bail: 2136 return annoArrayArray; 2137 } 2138 2139 /* 2140 * Find the DexAnnotationSetItem for this parameter. 2141 * 2142 * Returns NULL if none found. 2143 */ 2144 static const DexParameterAnnotationsItem* findAnnotationsItemForMethod( 2145 const Method* method) 2146 { 2147 ClassObject* clazz = method->clazz; 2148 DexFile* pDexFile; 2149 const DexAnnotationsDirectoryItem* pAnnoDir; 2150 const DexParameterAnnotationsItem* pParameterList; 2151 2152 if (clazz->pDvmDex == NULL) /* generated class (Proxy, array) */ 2153 return NULL; 2154 2155 pDexFile = clazz->pDvmDex->pDexFile; 2156 pAnnoDir = getAnnoDirectory(pDexFile, clazz); 2157 if (pAnnoDir == NULL) 2158 return NULL; 2159 2160 pParameterList = dexGetParameterAnnotations(pDexFile, pAnnoDir); 2161 if (pParameterList == NULL) 2162 return NULL; 2163 2164 /* 2165 * Run through the list and find a matching method. We compare the 2166 * method ref indices in the annotation list with the method's DEX 2167 * method_idx value. 2168 * 2169 * TODO: use a binary search for long lists 2170 * 2171 * Alternate approach: for each entry in the annotations list, 2172 * find the method definition in the DEX file and perform string 2173 * comparisons on class name, method name, and signature. 2174 */ 2175 u4 methodIdx = getMethodIdx(method); 2176 u4 count = dexGetParameterAnnotationsSize(pDexFile, pAnnoDir); 2177 u4 idx; 2178 2179 for (idx = 0; idx < count; idx++) { 2180 if (pParameterList[idx].methodIdx == methodIdx) { 2181 /* found! */ 2182 return &pParameterList[idx]; 2183 } 2184 } 2185 2186 return NULL; 2187 } 2188 2189 2190 /* 2191 * Count up the number of arguments the method takes. The "this" pointer 2192 * doesn't count. 2193 */ 2194 static int countMethodArguments(const Method* method) 2195 { 2196 /* method->shorty[0] is the return type */ 2197 return strlen(method->shorty + 1); 2198 } 2199 2200 /* 2201 * Return an array of arrays of Annotation objects. The outer array has 2202 * one entry per method parameter, the inner array has the list of annotations 2203 * associated with that parameter. 2204 * 2205 * If the method has no parameters, we return an array of length zero. If 2206 * the method has one or more parameters, we return an array whose length 2207 * is equal to the number of parameters; if a given parameter does not have 2208 * an annotation, the corresponding entry will be null. 2209 * 2210 * Caller must call dvmReleaseTrackedAlloc(). 2211 */ 2212 ArrayObject* dvmGetParameterAnnotations(const Method* method) 2213 { 2214 ClassObject* clazz = method->clazz; 2215 const DexParameterAnnotationsItem* pItem; 2216 ArrayObject* annoArrayArray = NULL; 2217 2218 pItem = findAnnotationsItemForMethod(method); 2219 if (pItem != NULL) { 2220 DexFile* pDexFile = clazz->pDvmDex->pDexFile; 2221 const DexAnnotationSetRefList* pAnnoSetList; 2222 u4 size; 2223 2224 size = dexGetParameterAnnotationSetRefSize(pDexFile, pItem); 2225 pAnnoSetList = dexGetParameterAnnotationSetRefList(pDexFile, pItem); 2226 annoArrayArray = processAnnotationSetRefList(clazz, pAnnoSetList, size); 2227 } else { 2228 /* no matching annotations found */ 2229 annoArrayArray = emptyAnnoArrayArray(countMethodArguments(method)); 2230 } 2231 2232 return annoArrayArray; 2233 } 2234 2235 2236 /* 2237 * =========================================================================== 2238 * DexEncodedArray interpretation 2239 * =========================================================================== 2240 */ 2241 2242 /** 2243 * Initializes an encoded array iterator. 2244 * 2245 * @param iterator iterator to initialize 2246 * @param encodedArray encoded array to iterate over 2247 * @param clazz class to use when resolving strings and types 2248 */ 2249 void dvmEncodedArrayIteratorInitialize(EncodedArrayIterator* iterator, 2250 const DexEncodedArray* encodedArray, const ClassObject* clazz) { 2251 iterator->encodedArray = encodedArray; 2252 iterator->cursor = encodedArray->array; 2253 iterator->size = readUleb128(&iterator->cursor); 2254 iterator->elementsLeft = iterator->size; 2255 iterator->clazz = clazz; 2256 } 2257 2258 /** 2259 * Returns whether there are more elements to be read. 2260 */ 2261 bool dvmEncodedArrayIteratorHasNext(const EncodedArrayIterator* iterator) { 2262 return (iterator->elementsLeft != 0); 2263 } 2264 2265 /** 2266 * Returns the next decoded value from the iterator, advancing its 2267 * cursor. This returns primitive values in their corresponding union 2268 * slots, and returns everything else (including nulls) as object 2269 * references in the "l" union slot. 2270 * 2271 * The caller must call dvmReleaseTrackedAlloc() on any returned reference. 2272 * 2273 * @param value pointer to store decoded value into 2274 * @returns true if a value was decoded and the cursor advanced; false if 2275 * the last value had already been decoded or if there was a problem decoding 2276 */ 2277 bool dvmEncodedArrayIteratorGetNext(EncodedArrayIterator* iterator, 2278 AnnotationValue* value) { 2279 bool processed; 2280 2281 if (iterator->elementsLeft == 0) { 2282 return false; 2283 } 2284 2285 processed = processAnnotationValue(iterator->clazz, &iterator->cursor, 2286 value, kPrimitivesOrObjects); 2287 2288 if (! processed) { 2289 ALOGE("Failed to process array element %d from %p", 2290 iterator->size - iterator->elementsLeft, 2291 iterator->encodedArray); 2292 iterator->elementsLeft = 0; 2293 return false; 2294 } 2295 2296 iterator->elementsLeft--; 2297 return true; 2298 } 2299