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