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