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 /* 18 * Dalvik bytecode structural verifier. The only public entry point 19 * (except for a few shared utility functions) is dvmVerifyCodeFlow(). 20 * 21 * TODO: might benefit from a signature-->class lookup cache. Could avoid 22 * some string-peeling and wouldn't need to compute hashes. 23 * 24 * TODO: we do too much stuff in here that could be done in the static 25 * verification pass. It's convenient, because we have all of the 26 * necessary information, but it's more efficient to do it over in 27 * DexVerify.c because in here we may have to process instructions 28 * multiple times. 29 */ 30 #include "Dalvik.h" 31 #include "analysis/CodeVerify.h" 32 #include "analysis/Optimize.h" 33 #include "analysis/RegisterMap.h" 34 #include "libdex/DexCatch.h" 35 #include "libdex/InstrUtils.h" 36 37 #include <stddef.h> 38 39 40 /* 41 * We don't need to store the register data for many instructions, because 42 * we either only need it at branch points (for verification) or GC points 43 * and branches (for verification + type-precise register analysis). 44 */ 45 typedef enum RegisterTrackingMode { 46 kTrackRegsBranches, 47 kTrackRegsGcPoints, 48 kTrackRegsAll 49 } RegisterTrackingMode; 50 51 /* 52 * Set this to enable dead code scanning. This is not required, but it's 53 * very useful when testing changes to the verifier (to make sure we're not 54 * skipping over stuff) and for checking the optimized output from "dx". 55 * The only reason not to do it is that it slightly increases the time 56 * required to perform verification. 57 */ 58 #define DEAD_CODE_SCAN true 59 60 static bool gDebugVerbose = false; // TODO: remove this 61 62 #if 0 63 int gDvm__totalInstr = 0; 64 int gDvm__gcInstr = 0; 65 int gDvm__gcData = 0; 66 int gDvm__gcSimpleData = 0; 67 #endif 68 69 /* 70 * Selectively enable verbose debug logging -- use this to activate 71 * dumpRegTypes() calls for all instructions in the specified method. 72 */ 73 static inline bool doVerboseLogging(const Method* meth) { 74 return false; /* COMMENT OUT to enable verbose debugging */ 75 76 const char* cd = "Landroid/net/http/Request;"; 77 const char* mn = "readResponse"; 78 const char* sg = "(Landroid/net/http/AndroidHttpClientConnection;)V"; 79 return (strcmp(meth->clazz->descriptor, cd) == 0 && 80 dvmCompareNameDescriptorAndMethod(mn, sg, meth) == 0); 81 } 82 83 #define SHOW_REG_DETAILS (0 /*| DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS*/) 84 85 /* 86 * We need an extra "pseudo register" to hold the return type briefly. It 87 * can be category 1 or 2, so we need two slots. 88 */ 89 #define kExtraRegs 2 90 #define RESULT_REGISTER(_insnRegCount) (_insnRegCount) 91 92 /* 93 * Big fat collection of registers. 94 */ 95 typedef struct RegisterTable { 96 /* 97 * Array of RegType arrays, one per address in the method. We only 98 * set the pointers for certain addresses, based on what we're trying 99 * to accomplish. 100 */ 101 RegType** addrRegs; 102 103 /* 104 * Number of registers we track for each instruction. This is equal 105 * to the method's declared "registersSize" plus kExtraRegs. 106 */ 107 int insnRegCountPlus; 108 109 /* 110 * A single large alloc, with all of the storage needed for addrRegs. 111 */ 112 RegType* regAlloc; 113 } RegisterTable; 114 115 116 /* fwd */ 117 #ifndef NDEBUG 118 static void checkMergeTab(void); 119 #endif 120 static bool isInitMethod(const Method* meth); 121 static RegType getInvocationThis(const RegType* insnRegs,\ 122 const int insnRegCount, const DecodedInstruction* pDecInsn, 123 VerifyError* pFailure); 124 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,\ 125 u4 vsrc, RegType checkType, VerifyError* pFailure); 126 static bool doCodeVerification(const Method* meth, InsnFlags* insnFlags,\ 127 RegisterTable* regTable, UninitInstanceMap* uninitMap); 128 static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,\ 129 RegisterTable* regTable, RegType* workRegs, int insnIdx, 130 UninitInstanceMap* uninitMap, int* pStartGuess); 131 static ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2); 132 static void dumpRegTypes(const Method* meth, const InsnFlags* insnFlags,\ 133 const RegType* addrRegs, int addr, const char* addrName, 134 const UninitInstanceMap* uninitMap, int displayFlags); 135 136 /* bit values for dumpRegTypes() "displayFlags" */ 137 enum { 138 DRT_SIMPLE = 0, 139 DRT_SHOW_REF_TYPES = 0x01, 140 DRT_SHOW_LOCALS = 0x02, 141 }; 142 143 144 /* 145 * =========================================================================== 146 * RegType and UninitInstanceMap utility functions 147 * =========================================================================== 148 */ 149 150 #define __ kRegTypeUnknown 151 #define _U kRegTypeUninit 152 #define _X kRegTypeConflict 153 #define _F kRegTypeFloat 154 #define _0 kRegTypeZero 155 #define _1 kRegTypeOne 156 #define _Z kRegTypeBoolean 157 #define _b kRegTypePosByte 158 #define _B kRegTypeByte 159 #define _s kRegTypePosShort 160 #define _S kRegTypeShort 161 #define _C kRegTypeChar 162 #define _I kRegTypeInteger 163 #define _J kRegTypeLongLo 164 #define _j kRegTypeLongHi 165 #define _D kRegTypeDoubleLo 166 #define _d kRegTypeDoubleHi 167 168 /* 169 * Merge result table for primitive values. The table is symmetric along 170 * the diagonal. 171 * 172 * Note that 32-bit int/float do not merge into 64-bit long/double. This 173 * is a register merge, not a widening conversion. Only the "implicit" 174 * widening within a category, e.g. byte to short, is allowed. 175 * 176 * Because Dalvik does not draw a distinction between int and float, we 177 * have to allow free exchange between 32-bit int/float and 64-bit 178 * long/double. 179 * 180 * Note that Uninit+Uninit=Uninit. This holds true because we only 181 * use this when the RegType value is exactly equal to kRegTypeUninit, which 182 * can only happen for the zeroeth entry in the table. 183 * 184 * "Unknown" never merges with anything known. The only time a register 185 * transitions from "unknown" to "known" is when we're executing code 186 * for the first time, and we handle that with a simple copy. 187 */ 188 const char gDvmMergeTab[kRegTypeMAX][kRegTypeMAX] = 189 { 190 /* chk: _ U X F 0 1 Z b B s S C I J j D d */ 191 { /*_*/ __,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X }, 192 { /*U*/ _X,_U,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X }, 193 { /*X*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X }, 194 { /*F*/ _X,_X,_X,_F,_F,_F,_F,_F,_F,_F,_F,_F,_F,_X,_X,_X,_X }, 195 { /*0*/ _X,_X,_X,_F,_0,_Z,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X }, 196 { /*1*/ _X,_X,_X,_F,_Z,_1,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X }, 197 { /*Z*/ _X,_X,_X,_F,_Z,_Z,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X }, 198 { /*b*/ _X,_X,_X,_F,_b,_b,_b,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X }, 199 { /*B*/ _X,_X,_X,_F,_B,_B,_B,_B,_B,_S,_S,_I,_I,_X,_X,_X,_X }, 200 { /*s*/ _X,_X,_X,_F,_s,_s,_s,_s,_S,_s,_S,_C,_I,_X,_X,_X,_X }, 201 { /*S*/ _X,_X,_X,_F,_S,_S,_S,_S,_S,_S,_S,_I,_I,_X,_X,_X,_X }, 202 { /*C*/ _X,_X,_X,_F,_C,_C,_C,_C,_I,_C,_I,_C,_I,_X,_X,_X,_X }, 203 { /*I*/ _X,_X,_X,_F,_I,_I,_I,_I,_I,_I,_I,_I,_I,_X,_X,_X,_X }, 204 { /*J*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_J,_X,_J,_X }, 205 { /*j*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_j,_X,_j }, 206 { /*D*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_J,_X,_D,_X }, 207 { /*d*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_j,_X,_d }, 208 }; 209 210 #undef __ 211 #undef _U 212 #undef _X 213 #undef _F 214 #undef _0 215 #undef _1 216 #undef _Z 217 #undef _b 218 #undef _B 219 #undef _s 220 #undef _S 221 #undef _C 222 #undef _I 223 #undef _J 224 #undef _j 225 #undef _D 226 #undef _d 227 228 #ifndef NDEBUG 229 /* 230 * Verify symmetry in the conversion table. 231 */ 232 static void checkMergeTab(void) 233 { 234 int i, j; 235 236 for (i = 0; i < kRegTypeMAX; i++) { 237 for (j = i; j < kRegTypeMAX; j++) { 238 if (gDvmMergeTab[i][j] != gDvmMergeTab[j][i]) { 239 LOGE("Symmetry violation: %d,%d vs %d,%d\n", i, j, j, i); 240 dvmAbort(); 241 } 242 } 243 } 244 } 245 #endif 246 247 /* 248 * Determine whether we can convert "srcType" to "checkType", where 249 * "checkType" is one of the category-1 non-reference types. 250 * 251 * 32-bit int and float are interchangeable. 252 */ 253 static bool canConvertTo1nr(RegType srcType, RegType checkType) 254 { 255 static const char convTab 256 [kRegType1nrEND-kRegType1nrSTART+1][kRegType1nrEND-kRegType1nrSTART+1] = 257 { 258 /* chk: F 0 1 Z b B s S C I */ 259 { /*F*/ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 260 { /*0*/ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 }, 261 { /*1*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 }, 262 { /*Z*/ 1, 0, 0, 1, 1, 1, 1, 1, 1, 1 }, 263 { /*b*/ 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 }, 264 { /*B*/ 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 }, 265 { /*s*/ 1, 0, 0, 0, 0, 0, 1, 1, 1, 1 }, 266 { /*S*/ 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, 267 { /*C*/ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 }, 268 { /*I*/ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, 269 }; 270 271 assert(checkType >= kRegType1nrSTART && checkType <= kRegType1nrEND); 272 #if 0 273 if (checkType < kRegType1nrSTART || checkType > kRegType1nrEND) { 274 LOG_VFY("Unexpected checkType %d (srcType=%d)\n", checkType, srcType); 275 assert(false); 276 return false; 277 } 278 #endif 279 280 //printf("convTab[%d][%d] = %d\n", srcType, checkType, 281 // convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART]); 282 if (srcType >= kRegType1nrSTART && srcType <= kRegType1nrEND) 283 return (bool) convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART]; 284 285 return false; 286 } 287 288 /* 289 * Determine whether the types are compatible. In Dalvik, 64-bit doubles 290 * and longs are interchangeable. 291 */ 292 static bool canConvertTo2(RegType srcType, RegType checkType) 293 { 294 return ((srcType == kRegTypeLongLo || srcType == kRegTypeDoubleLo) && 295 (checkType == kRegTypeLongLo || checkType == kRegTypeDoubleLo)); 296 } 297 298 /* 299 * Determine whether or not "instrType" and "targetType" are compatible, 300 * for purposes of getting or setting a value in a field or array. The 301 * idea is that an instruction with a category 1nr type (say, aget-short 302 * or iput-boolean) is accessing a static field, instance field, or array 303 * entry, and we want to make sure sure that the operation is legal. 304 * 305 * At a minimum, source and destination must have the same width. We 306 * further refine this to assert that "short" and "char" are not 307 * compatible, because the sign-extension is different on the "get" 308 * operations. As usual, "float" and "int" are interoperable. 309 * 310 * We're not considering the actual contents of the register, so we'll 311 * never get "pseudo-types" like kRegTypeZero or kRegTypePosShort. We 312 * could get kRegTypeUnknown in "targetType" if a field or array class 313 * lookup failed. Category 2 types and references are checked elsewhere. 314 */ 315 static bool checkFieldArrayStore1nr(RegType instrType, RegType targetType) 316 { 317 if (instrType == targetType) 318 return true; /* quick positive; most common case */ 319 320 if ((instrType == kRegTypeInteger && targetType == kRegTypeFloat) || 321 (instrType == kRegTypeFloat && targetType == kRegTypeInteger)) 322 { 323 return true; 324 } 325 326 return false; 327 } 328 329 /* 330 * Convert a VM PrimitiveType enum value to the equivalent RegType value. 331 */ 332 static RegType primitiveTypeToRegType(PrimitiveType primType) 333 { 334 static const struct { 335 RegType regType; /* type equivalent */ 336 PrimitiveType primType; /* verification */ 337 } convTab[] = { 338 /* must match order of enum in Object.h */ 339 { kRegTypeBoolean, PRIM_BOOLEAN }, 340 { kRegTypeChar, PRIM_CHAR }, 341 { kRegTypeFloat, PRIM_FLOAT }, 342 { kRegTypeDoubleLo, PRIM_DOUBLE }, 343 { kRegTypeByte, PRIM_BYTE }, 344 { kRegTypeShort, PRIM_SHORT }, 345 { kRegTypeInteger, PRIM_INT }, 346 { kRegTypeLongLo, PRIM_LONG }, 347 // PRIM_VOID 348 }; 349 350 if (primType < 0 || primType > (int) (sizeof(convTab) / sizeof(convTab[0]))) 351 { 352 assert(false); 353 return kRegTypeUnknown; 354 } 355 356 assert(convTab[primType].primType == primType); 357 return convTab[primType].regType; 358 } 359 360 /* 361 * Create a new uninitialized instance map. 362 * 363 * The map is allocated and populated with address entries. The addresses 364 * appear in ascending order to allow binary searching. 365 * 366 * Very few methods have 10 or more new-instance instructions; the 367 * majority have 0 or 1. Occasionally a static initializer will have 200+. 368 */ 369 UninitInstanceMap* dvmCreateUninitInstanceMap(const Method* meth, 370 const InsnFlags* insnFlags, int newInstanceCount) 371 { 372 const int insnsSize = dvmGetMethodInsnsSize(meth); 373 const u2* insns = meth->insns; 374 UninitInstanceMap* uninitMap; 375 bool isInit = false; 376 int idx, addr; 377 378 if (isInitMethod(meth)) { 379 newInstanceCount++; 380 isInit = true; 381 } 382 383 /* 384 * Allocate the header and map as a single unit. 385 * 386 * TODO: consider having a static instance so we can avoid allocations. 387 * I don't think the verifier is guaranteed to be single-threaded when 388 * running in the VM (rather than dexopt), so that must be taken into 389 * account. 390 */ 391 int size = offsetof(UninitInstanceMap, map) + 392 newInstanceCount * sizeof(uninitMap->map[0]); 393 uninitMap = calloc(1, size); 394 if (uninitMap == NULL) 395 return NULL; 396 uninitMap->numEntries = newInstanceCount; 397 398 idx = 0; 399 if (isInit) { 400 uninitMap->map[idx++].addr = kUninitThisArgAddr; 401 } 402 403 /* 404 * Run through and find the new-instance instructions. 405 */ 406 for (addr = 0; addr < insnsSize; /**/) { 407 int width = dvmInsnGetWidth(insnFlags, addr); 408 409 if ((*insns & 0xff) == OP_NEW_INSTANCE) 410 uninitMap->map[idx++].addr = addr; 411 412 addr += width; 413 insns += width; 414 } 415 416 assert(idx == newInstanceCount); 417 return uninitMap; 418 } 419 420 /* 421 * Free the map. 422 */ 423 void dvmFreeUninitInstanceMap(UninitInstanceMap* uninitMap) 424 { 425 free(uninitMap); 426 } 427 428 /* 429 * Set the class object associated with the instruction at "addr". 430 * 431 * Returns the map slot index, or -1 if the address isn't listed in the map 432 * (shouldn't happen) or if a class is already associated with the address 433 * (bad bytecode). 434 * 435 * Entries, once set, do not change -- a given address can only allocate 436 * one type of object. 437 */ 438 int dvmSetUninitInstance(UninitInstanceMap* uninitMap, int addr, 439 ClassObject* clazz) 440 { 441 int idx; 442 443 assert(clazz != NULL); 444 445 /* TODO: binary search when numEntries > 8 */ 446 for (idx = uninitMap->numEntries - 1; idx >= 0; idx--) { 447 if (uninitMap->map[idx].addr == addr) { 448 if (uninitMap->map[idx].clazz != NULL && 449 uninitMap->map[idx].clazz != clazz) 450 { 451 LOG_VFY("VFY: addr %d already set to %p, not setting to %p\n", 452 addr, uninitMap->map[idx].clazz, clazz); 453 return -1; // already set to something else?? 454 } 455 uninitMap->map[idx].clazz = clazz; 456 return idx; 457 } 458 } 459 460 LOG_VFY("VFY: addr %d not found in uninit map\n", addr); 461 assert(false); // shouldn't happen 462 return -1; 463 } 464 465 /* 466 * Get the class object at the specified index. 467 */ 468 ClassObject* dvmGetUninitInstance(const UninitInstanceMap* uninitMap, int idx) 469 { 470 assert(idx >= 0 && idx < uninitMap->numEntries); 471 return uninitMap->map[idx].clazz; 472 } 473 474 /* determine if "type" is actually an object reference (init/uninit/zero) */ 475 static inline bool regTypeIsReference(RegType type) { 476 return (type > kRegTypeMAX || type == kRegTypeUninit || 477 type == kRegTypeZero); 478 } 479 480 /* determine if "type" is an uninitialized object reference */ 481 static inline bool regTypeIsUninitReference(RegType type) { 482 return ((type & kRegTypeUninitMask) == kRegTypeUninit); 483 } 484 485 /* convert the initialized reference "type" to a ClassObject pointer */ 486 /* (does not expect uninit ref types or "zero") */ 487 static ClassObject* regTypeInitializedReferenceToClass(RegType type) 488 { 489 assert(regTypeIsReference(type) && type != kRegTypeZero); 490 if ((type & 0x01) == 0) { 491 return (ClassObject*) type; 492 } else { 493 //LOG_VFY("VFY: attempted to use uninitialized reference\n"); 494 return NULL; 495 } 496 } 497 498 /* extract the index into the uninitialized instance map table */ 499 static inline int regTypeToUninitIndex(RegType type) { 500 assert(regTypeIsUninitReference(type)); 501 return (type & ~kRegTypeUninitMask) >> kRegTypeUninitShift; 502 } 503 504 /* convert the reference "type" to a ClassObject pointer */ 505 static ClassObject* regTypeReferenceToClass(RegType type, 506 const UninitInstanceMap* uninitMap) 507 { 508 assert(regTypeIsReference(type) && type != kRegTypeZero); 509 if (regTypeIsUninitReference(type)) { 510 assert(uninitMap != NULL); 511 return dvmGetUninitInstance(uninitMap, regTypeToUninitIndex(type)); 512 } else { 513 return (ClassObject*) type; 514 } 515 } 516 517 /* convert the ClassObject pointer to an (initialized) register type */ 518 static inline RegType regTypeFromClass(ClassObject* clazz) { 519 return (u4) clazz; 520 } 521 522 /* return the RegType for the uninitialized reference in slot "uidx" */ 523 static RegType regTypeFromUninitIndex(int uidx) { 524 return (u4) (kRegTypeUninit | (uidx << kRegTypeUninitShift)); 525 } 526 527 528 /* 529 * =========================================================================== 530 * Signature operations 531 * =========================================================================== 532 */ 533 534 /* 535 * Is this method a constructor? 536 */ 537 static bool isInitMethod(const Method* meth) 538 { 539 return (*meth->name == '<' && strcmp(meth->name+1, "init>") == 0); 540 } 541 542 /* 543 * Is this method a class initializer? 544 */ 545 #if 0 546 static bool isClassInitMethod(const Method* meth) 547 { 548 return (*meth->name == '<' && strcmp(meth->name+1, "clinit>") == 0); 549 } 550 #endif 551 552 /* 553 * Look up a class reference given as a simple string descriptor. 554 * 555 * If we can't find it, return a generic substitute when possible. 556 */ 557 static ClassObject* lookupClassByDescriptor(const Method* meth, 558 const char* pDescriptor, VerifyError* pFailure) 559 { 560 /* 561 * The javac compiler occasionally puts references to nonexistent 562 * classes in signatures. For example, if you have a non-static 563 * inner class with no constructor, the compiler provides 564 * a private <init> for you. Constructing the class 565 * requires <init>(parent), but the outer class can't call 566 * that because the method is private. So the compiler 567 * generates a package-scope <init>(parent,bogus) method that 568 * just calls the regular <init> (the "bogus" part being necessary 569 * to distinguish the signature of the synthetic method). 570 * Treating the bogus class as an instance of java.lang.Object 571 * allows the verifier to process the class successfully. 572 */ 573 574 //LOGI("Looking up '%s'\n", typeStr); 575 ClassObject* clazz; 576 clazz = dvmFindClassNoInit(pDescriptor, meth->clazz->classLoader); 577 if (clazz == NULL) { 578 dvmClearOptException(dvmThreadSelf()); 579 if (strchr(pDescriptor, '$') != NULL) { 580 LOGV("VFY: unable to find class referenced in signature (%s)\n", 581 pDescriptor); 582 } else { 583 LOG_VFY("VFY: unable to find class referenced in signature (%s)\n", 584 pDescriptor); 585 } 586 587 if (pDescriptor[0] == '[') { 588 /* We are looking at an array descriptor. */ 589 590 /* 591 * There should never be a problem loading primitive arrays. 592 */ 593 if (pDescriptor[1] != 'L' && pDescriptor[1] != '[') { 594 LOG_VFY("VFY: invalid char in signature in '%s'\n", 595 pDescriptor); 596 *pFailure = VERIFY_ERROR_GENERIC; 597 } 598 599 /* 600 * Try to continue with base array type. This will let 601 * us pass basic stuff (e.g. get array len) that wouldn't 602 * fly with an Object. This is NOT correct if the 603 * missing type is a primitive array, but we should never 604 * have a problem loading those. (I'm not convinced this 605 * is correct or even useful. Just use Object here?) 606 */ 607 clazz = dvmFindClassNoInit("[Ljava/lang/Object;", 608 meth->clazz->classLoader); 609 } else if (pDescriptor[0] == 'L') { 610 /* 611 * We are looking at a non-array reference descriptor; 612 * try to continue with base reference type. 613 */ 614 clazz = gDvm.classJavaLangObject; 615 } else { 616 /* We are looking at a primitive type. */ 617 LOG_VFY("VFY: invalid char in signature in '%s'\n", pDescriptor); 618 *pFailure = VERIFY_ERROR_GENERIC; 619 } 620 621 if (clazz == NULL) { 622 *pFailure = VERIFY_ERROR_GENERIC; 623 } 624 } 625 626 if (dvmIsPrimitiveClass(clazz)) { 627 LOG_VFY("VFY: invalid use of primitive type '%s'\n", pDescriptor); 628 *pFailure = VERIFY_ERROR_GENERIC; 629 clazz = NULL; 630 } 631 632 return clazz; 633 } 634 635 /* 636 * Look up a class reference in a signature. Could be an arg or the 637 * return value. 638 * 639 * Advances "*pSig" to the last character in the signature (that is, to 640 * the ';'). 641 * 642 * NOTE: this is also expected to verify the signature. 643 */ 644 static ClassObject* lookupSignatureClass(const Method* meth, const char** pSig, 645 VerifyError* pFailure) 646 { 647 const char* sig = *pSig; 648 const char* endp = sig; 649 650 assert(sig != NULL && *sig == 'L'); 651 652 while (*++endp != ';' && *endp != '\0') 653 ; 654 if (*endp != ';') { 655 LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig); 656 *pFailure = VERIFY_ERROR_GENERIC; 657 return NULL; 658 } 659 660 endp++; /* Advance past the ';'. */ 661 int typeLen = endp - sig; 662 char typeStr[typeLen+1]; /* +1 for the '\0' */ 663 memcpy(typeStr, sig, typeLen); 664 typeStr[typeLen] = '\0'; 665 666 *pSig = endp - 1; /* - 1 so that *pSig points at, not past, the ';' */ 667 668 return lookupClassByDescriptor(meth, typeStr, pFailure); 669 } 670 671 /* 672 * Look up an array class reference in a signature. Could be an arg or the 673 * return value. 674 * 675 * Advances "*pSig" to the last character in the signature. 676 * 677 * NOTE: this is also expected to verify the signature. 678 */ 679 static ClassObject* lookupSignatureArrayClass(const Method* meth, 680 const char** pSig, VerifyError* pFailure) 681 { 682 const char* sig = *pSig; 683 const char* endp = sig; 684 685 assert(sig != NULL && *sig == '['); 686 687 /* find the end */ 688 while (*++endp == '[' && *endp != '\0') 689 ; 690 691 if (*endp == 'L') { 692 while (*++endp != ';' && *endp != '\0') 693 ; 694 if (*endp != ';') { 695 LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig); 696 *pFailure = VERIFY_ERROR_GENERIC; 697 return NULL; 698 } 699 } 700 701 int typeLen = endp - sig +1; 702 char typeStr[typeLen+1]; 703 memcpy(typeStr, sig, typeLen); 704 typeStr[typeLen] = '\0'; 705 706 *pSig = endp; 707 708 return lookupClassByDescriptor(meth, typeStr, pFailure); 709 } 710 711 /* 712 * Set the register types for the first instruction in the method based on 713 * the method signature. 714 * 715 * This has the side-effect of validating the signature. 716 * 717 * Returns "true" on success. 718 */ 719 static bool setTypesFromSignature(const Method* meth, RegType* regTypes, 720 UninitInstanceMap* uninitMap) 721 { 722 DexParameterIterator iterator; 723 int actualArgs, expectedArgs, argStart; 724 VerifyError failure = VERIFY_ERROR_NONE; 725 726 dexParameterIteratorInit(&iterator, &meth->prototype); 727 argStart = meth->registersSize - meth->insSize; 728 expectedArgs = meth->insSize; /* long/double count as two */ 729 actualArgs = 0; 730 731 assert(argStart >= 0); /* should have been verified earlier */ 732 733 /* 734 * Include the "this" pointer. 735 */ 736 if (!dvmIsStaticMethod(meth)) { 737 /* 738 * If this is a constructor for a class other than java.lang.Object, 739 * mark the first ("this") argument as uninitialized. This restricts 740 * field access until the superclass constructor is called. 741 */ 742 if (isInitMethod(meth) && meth->clazz != gDvm.classJavaLangObject) { 743 int uidx = dvmSetUninitInstance(uninitMap, kUninitThisArgAddr, 744 meth->clazz); 745 assert(uidx == 0); 746 regTypes[argStart + actualArgs] = regTypeFromUninitIndex(uidx); 747 } else { 748 regTypes[argStart + actualArgs] = regTypeFromClass(meth->clazz); 749 } 750 actualArgs++; 751 } 752 753 for (;;) { 754 const char* descriptor = dexParameterIteratorNextDescriptor(&iterator); 755 756 if (descriptor == NULL) { 757 break; 758 } 759 760 if (actualArgs >= expectedArgs) { 761 LOG_VFY("VFY: expected %d args, found more (%s)\n", 762 expectedArgs, descriptor); 763 goto bad_sig; 764 } 765 766 switch (*descriptor) { 767 case 'L': 768 case '[': 769 /* 770 * We assume that reference arguments are initialized. The 771 * only way it could be otherwise (assuming the caller was 772 * verified) is if the current method is <init>, but in that 773 * case it's effectively considered initialized the instant 774 * we reach here (in the sense that we can return without 775 * doing anything or call virtual methods). 776 */ 777 { 778 ClassObject* clazz = 779 lookupClassByDescriptor(meth, descriptor, &failure); 780 if (!VERIFY_OK(failure)) 781 goto bad_sig; 782 regTypes[argStart + actualArgs] = regTypeFromClass(clazz); 783 } 784 actualArgs++; 785 break; 786 case 'Z': 787 regTypes[argStart + actualArgs] = kRegTypeBoolean; 788 actualArgs++; 789 break; 790 case 'C': 791 regTypes[argStart + actualArgs] = kRegTypeChar; 792 actualArgs++; 793 break; 794 case 'B': 795 regTypes[argStart + actualArgs] = kRegTypeByte; 796 actualArgs++; 797 break; 798 case 'I': 799 regTypes[argStart + actualArgs] = kRegTypeInteger; 800 actualArgs++; 801 break; 802 case 'S': 803 regTypes[argStart + actualArgs] = kRegTypeShort; 804 actualArgs++; 805 break; 806 case 'F': 807 regTypes[argStart + actualArgs] = kRegTypeFloat; 808 actualArgs++; 809 break; 810 case 'D': 811 regTypes[argStart + actualArgs] = kRegTypeDoubleLo; 812 regTypes[argStart + actualArgs +1] = kRegTypeDoubleHi; 813 actualArgs += 2; 814 break; 815 case 'J': 816 regTypes[argStart + actualArgs] = kRegTypeLongLo; 817 regTypes[argStart + actualArgs +1] = kRegTypeLongHi; 818 actualArgs += 2; 819 break; 820 default: 821 LOG_VFY("VFY: unexpected signature type char '%c'\n", *descriptor); 822 goto bad_sig; 823 } 824 } 825 826 if (actualArgs != expectedArgs) { 827 LOG_VFY("VFY: expected %d args, found %d\n", expectedArgs, actualArgs); 828 goto bad_sig; 829 } 830 831 const char* descriptor = dexProtoGetReturnType(&meth->prototype); 832 833 /* 834 * Validate return type. We don't do the type lookup; just want to make 835 * sure that it has the right format. Only major difference from the 836 * method argument format is that 'V' is supported. 837 */ 838 switch (*descriptor) { 839 case 'I': 840 case 'C': 841 case 'S': 842 case 'B': 843 case 'Z': 844 case 'V': 845 case 'F': 846 case 'D': 847 case 'J': 848 if (*(descriptor+1) != '\0') 849 goto bad_sig; 850 break; 851 case '[': 852 /* single/multi, object/primitive */ 853 while (*++descriptor == '[') 854 ; 855 if (*descriptor == 'L') { 856 while (*++descriptor != ';' && *descriptor != '\0') 857 ; 858 if (*descriptor != ';') 859 goto bad_sig; 860 } else { 861 if (*(descriptor+1) != '\0') 862 goto bad_sig; 863 } 864 break; 865 case 'L': 866 /* could be more thorough here, but shouldn't be required */ 867 while (*++descriptor != ';' && *descriptor != '\0') 868 ; 869 if (*descriptor != ';') 870 goto bad_sig; 871 break; 872 default: 873 goto bad_sig; 874 } 875 876 return true; 877 878 //fail: 879 // LOG_VFY_METH(meth, "VFY: bad sig\n"); 880 // return false; 881 882 bad_sig: 883 { 884 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 885 LOG_VFY("VFY: bad signature '%s' for %s.%s\n", 886 desc, meth->clazz->descriptor, meth->name); 887 free(desc); 888 } 889 return false; 890 } 891 892 /* 893 * Return the register type for the method. We can't just use the 894 * already-computed DalvikJniReturnType, because if it's a reference type 895 * we need to do the class lookup. 896 * 897 * Returned references are assumed to be initialized. 898 * 899 * Returns kRegTypeUnknown for "void". 900 */ 901 static RegType getMethodReturnType(const Method* meth) 902 { 903 RegType type; 904 const char* descriptor = dexProtoGetReturnType(&meth->prototype); 905 906 switch (*descriptor) { 907 case 'I': 908 type = kRegTypeInteger; 909 break; 910 case 'C': 911 type = kRegTypeChar; 912 break; 913 case 'S': 914 type = kRegTypeShort; 915 break; 916 case 'B': 917 type = kRegTypeByte; 918 break; 919 case 'Z': 920 type = kRegTypeBoolean; 921 break; 922 case 'V': 923 type = kRegTypeUnknown; 924 break; 925 case 'F': 926 type = kRegTypeFloat; 927 break; 928 case 'D': 929 type = kRegTypeDoubleLo; 930 break; 931 case 'J': 932 type = kRegTypeLongLo; 933 break; 934 case 'L': 935 case '[': 936 { 937 VerifyError failure = VERIFY_ERROR_NONE; 938 ClassObject* clazz = 939 lookupClassByDescriptor(meth, descriptor, &failure); 940 assert(VERIFY_OK(failure)); 941 type = regTypeFromClass(clazz); 942 } 943 break; 944 default: 945 /* we verified signature return type earlier, so this is impossible */ 946 assert(false); 947 type = kRegTypeConflict; 948 break; 949 } 950 951 return type; 952 } 953 954 /* 955 * Convert a single-character signature value (i.e. a primitive type) to 956 * the corresponding RegType. This is intended for access to object fields 957 * holding primitive types. 958 * 959 * Returns kRegTypeUnknown for objects, arrays, and void. 960 */ 961 static RegType primSigCharToRegType(char sigChar) 962 { 963 RegType type; 964 965 switch (sigChar) { 966 case 'I': 967 type = kRegTypeInteger; 968 break; 969 case 'C': 970 type = kRegTypeChar; 971 break; 972 case 'S': 973 type = kRegTypeShort; 974 break; 975 case 'B': 976 type = kRegTypeByte; 977 break; 978 case 'Z': 979 type = kRegTypeBoolean; 980 break; 981 case 'F': 982 type = kRegTypeFloat; 983 break; 984 case 'D': 985 type = kRegTypeDoubleLo; 986 break; 987 case 'J': 988 type = kRegTypeLongLo; 989 break; 990 case 'V': 991 case 'L': 992 case '[': 993 type = kRegTypeUnknown; 994 break; 995 default: 996 assert(false); 997 type = kRegTypeUnknown; 998 break; 999 } 1000 1001 return type; 1002 } 1003 1004 /* 1005 * See if the method matches the MethodType. 1006 */ 1007 static bool isCorrectInvokeKind(MethodType methodType, Method* resMethod) 1008 { 1009 switch (methodType) { 1010 case METHOD_DIRECT: 1011 return dvmIsDirectMethod(resMethod); 1012 case METHOD_STATIC: 1013 return dvmIsStaticMethod(resMethod); 1014 case METHOD_VIRTUAL: 1015 case METHOD_INTERFACE: 1016 return !dvmIsDirectMethod(resMethod); 1017 default: 1018 return false; 1019 } 1020 } 1021 1022 /* 1023 * Verify the arguments to a method. We're executing in "method", making 1024 * a call to the method reference in vB. 1025 * 1026 * If this is a "direct" invoke, we allow calls to <init>. For calls to 1027 * <init>, the first argument may be an uninitialized reference. Otherwise, 1028 * calls to anything starting with '<' will be rejected, as will any 1029 * uninitialized reference arguments. 1030 * 1031 * For non-static method calls, this will verify that the method call is 1032 * appropriate for the "this" argument. 1033 * 1034 * The method reference is in vBBBB. The "isRange" parameter determines 1035 * whether we use 0-4 "args" values or a range of registers defined by 1036 * vAA and vCCCC. 1037 * 1038 * Widening conversions on integers and references are allowed, but 1039 * narrowing conversions are not. 1040 * 1041 * Returns the resolved method on success, NULL on failure (with *pFailure 1042 * set appropriately). 1043 */ 1044 static Method* verifyInvocationArgs(const Method* meth, const RegType* insnRegs, 1045 const int insnRegCount, const DecodedInstruction* pDecInsn, 1046 UninitInstanceMap* uninitMap, MethodType methodType, bool isRange, 1047 bool isSuper, VerifyError* pFailure) 1048 { 1049 Method* resMethod; 1050 char* sigOriginal = NULL; 1051 1052 /* 1053 * Resolve the method. This could be an abstract or concrete method 1054 * depending on what sort of call we're making. 1055 */ 1056 if (methodType == METHOD_INTERFACE) { 1057 resMethod = dvmOptResolveInterfaceMethod(meth->clazz, pDecInsn->vB); 1058 } else { 1059 resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType, 1060 pFailure); 1061 } 1062 if (resMethod == NULL) { 1063 /* failed; print a meaningful failure message */ 1064 DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile; 1065 const DexMethodId* pMethodId; 1066 const char* methodName; 1067 char* methodDesc; 1068 const char* classDescriptor; 1069 1070 pMethodId = dexGetMethodId(pDexFile, pDecInsn->vB); 1071 methodName = dexStringById(pDexFile, pMethodId->nameIdx); 1072 methodDesc = dexCopyDescriptorFromMethodId(pDexFile, pMethodId); 1073 classDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx); 1074 1075 if (!gDvm.optimizing) { 1076 char* dotMissingClass = dvmDescriptorToDot(classDescriptor); 1077 char* dotMethClass = dvmDescriptorToDot(meth->clazz->descriptor); 1078 //char* curMethodDesc = 1079 // dexProtoCopyMethodDescriptor(&meth->prototype); 1080 1081 LOGI("Could not find method %s.%s, referenced from method %s.%s\n", 1082 dotMissingClass, methodName/*, methodDesc*/, 1083 dotMethClass, meth->name/*, curMethodDesc*/); 1084 1085 free(dotMissingClass); 1086 free(dotMethClass); 1087 //free(curMethodDesc); 1088 } 1089 1090 LOG_VFY("VFY: unable to resolve %s method %u: %s.%s %s\n", 1091 dvmMethodTypeStr(methodType), pDecInsn->vB, 1092 classDescriptor, methodName, methodDesc); 1093 free(methodDesc); 1094 if (VERIFY_OK(*pFailure)) /* not set for interface resolve */ 1095 *pFailure = VERIFY_ERROR_NO_METHOD; 1096 goto fail; 1097 } 1098 1099 /* 1100 * Only time you can explicitly call a method starting with '<' is when 1101 * making a "direct" invocation on "<init>". There are additional 1102 * restrictions but we don't enforce them here. 1103 */ 1104 if (resMethod->name[0] == '<') { 1105 if (methodType != METHOD_DIRECT || !isInitMethod(resMethod)) { 1106 LOG_VFY("VFY: invalid call to %s.%s\n", 1107 resMethod->clazz->descriptor, resMethod->name); 1108 goto bad_sig; 1109 } 1110 } 1111 1112 /* 1113 * See if the method type implied by the invoke instruction matches the 1114 * access flags for the target method. 1115 */ 1116 if (!isCorrectInvokeKind(methodType, resMethod)) { 1117 LOG_VFY("VFY: invoke type does not match method type of %s.%s\n", 1118 resMethod->clazz->descriptor, resMethod->name); 1119 goto fail; 1120 } 1121 1122 /* 1123 * If we're using invoke-super(method), make sure that the executing 1124 * method's class' superclass has a vtable entry for the target method. 1125 */ 1126 if (isSuper) { 1127 assert(methodType == METHOD_VIRTUAL); 1128 ClassObject* super = meth->clazz->super; 1129 if (super == NULL || resMethod->methodIndex > super->vtableCount) { 1130 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype); 1131 LOG_VFY("VFY: invalid invoke-super from %s.%s to super %s.%s %s\n", 1132 meth->clazz->descriptor, meth->name, 1133 (super == NULL) ? "-" : super->descriptor, 1134 resMethod->name, desc); 1135 free(desc); 1136 *pFailure = VERIFY_ERROR_NO_METHOD; 1137 goto fail; 1138 } 1139 } 1140 1141 /* 1142 * We use vAA as our expected arg count, rather than resMethod->insSize, 1143 * because we need to match the call to the signature. Also, we might 1144 * might be calling through an abstract method definition (which doesn't 1145 * have register count values). 1146 */ 1147 sigOriginal = dexProtoCopyMethodDescriptor(&resMethod->prototype); 1148 const char* sig = sigOriginal; 1149 int expectedArgs = pDecInsn->vA; 1150 int actualArgs = 0; 1151 1152 if (!isRange && expectedArgs > 5) { 1153 LOG_VFY("VFY: invalid arg count in non-range invoke (%d)\n", 1154 pDecInsn->vA); 1155 goto fail; 1156 } 1157 if (expectedArgs > meth->outsSize) { 1158 LOG_VFY("VFY: invalid arg count (%d) exceeds outsSize (%d)\n", 1159 expectedArgs, meth->outsSize); 1160 goto fail; 1161 } 1162 1163 if (*sig++ != '(') 1164 goto bad_sig; 1165 1166 /* 1167 * Check the "this" argument, which must be an instance of the class 1168 * that declared the method. For an interface class, we don't do the 1169 * full interface merge, so we can't do a rigorous check here (which 1170 * is okay since we have to do it at runtime). 1171 */ 1172 if (!dvmIsStaticMethod(resMethod)) { 1173 ClassObject* actualThisRef; 1174 RegType actualArgType; 1175 1176 actualArgType = getInvocationThis(insnRegs, insnRegCount, pDecInsn, 1177 pFailure); 1178 if (!VERIFY_OK(*pFailure)) 1179 goto fail; 1180 1181 if (regTypeIsUninitReference(actualArgType) && resMethod->name[0] != '<') 1182 { 1183 LOG_VFY("VFY: 'this' arg must be initialized\n"); 1184 goto fail; 1185 } 1186 if (methodType != METHOD_INTERFACE && actualArgType != kRegTypeZero) { 1187 actualThisRef = regTypeReferenceToClass(actualArgType, uninitMap); 1188 if (!dvmInstanceof(actualThisRef, resMethod->clazz)) { 1189 LOG_VFY("VFY: 'this' arg '%s' not instance of '%s'\n", 1190 actualThisRef->descriptor, 1191 resMethod->clazz->descriptor); 1192 goto fail; 1193 } 1194 } 1195 actualArgs++; 1196 } 1197 1198 /* 1199 * Process the target method's signature. This signature may or may not 1200 * have been verified, so we can't assume it's properly formed. 1201 */ 1202 while (*sig != '\0' && *sig != ')') { 1203 if (actualArgs >= expectedArgs) { 1204 LOG_VFY("VFY: expected %d args, found more (%c)\n", 1205 expectedArgs, *sig); 1206 goto bad_sig; 1207 } 1208 1209 u4 getReg; 1210 if (isRange) 1211 getReg = pDecInsn->vC + actualArgs; 1212 else 1213 getReg = pDecInsn->arg[actualArgs]; 1214 1215 switch (*sig) { 1216 case 'L': 1217 { 1218 ClassObject* clazz = lookupSignatureClass(meth, &sig, pFailure); 1219 if (!VERIFY_OK(*pFailure)) 1220 goto bad_sig; 1221 verifyRegisterType(insnRegs, insnRegCount, getReg, 1222 regTypeFromClass(clazz), pFailure); 1223 if (!VERIFY_OK(*pFailure)) { 1224 LOG_VFY("VFY: bad arg %d (into %s)\n", 1225 actualArgs, clazz->descriptor); 1226 goto bad_sig; 1227 } 1228 } 1229 actualArgs++; 1230 break; 1231 case '[': 1232 { 1233 ClassObject* clazz = 1234 lookupSignatureArrayClass(meth, &sig, pFailure); 1235 if (!VERIFY_OK(*pFailure)) 1236 goto bad_sig; 1237 verifyRegisterType(insnRegs, insnRegCount, getReg, 1238 regTypeFromClass(clazz), pFailure); 1239 if (!VERIFY_OK(*pFailure)) { 1240 LOG_VFY("VFY: bad arg %d (into %s)\n", 1241 actualArgs, clazz->descriptor); 1242 goto bad_sig; 1243 } 1244 } 1245 actualArgs++; 1246 break; 1247 case 'Z': 1248 verifyRegisterType(insnRegs, insnRegCount, getReg, 1249 kRegTypeBoolean, pFailure); 1250 actualArgs++; 1251 break; 1252 case 'C': 1253 verifyRegisterType(insnRegs, insnRegCount, getReg, 1254 kRegTypeChar, pFailure); 1255 actualArgs++; 1256 break; 1257 case 'B': 1258 verifyRegisterType(insnRegs, insnRegCount, getReg, 1259 kRegTypeByte, pFailure); 1260 actualArgs++; 1261 break; 1262 case 'I': 1263 verifyRegisterType(insnRegs, insnRegCount, getReg, 1264 kRegTypeInteger, pFailure); 1265 actualArgs++; 1266 break; 1267 case 'S': 1268 verifyRegisterType(insnRegs, insnRegCount, getReg, 1269 kRegTypeShort, pFailure); 1270 actualArgs++; 1271 break; 1272 case 'F': 1273 verifyRegisterType(insnRegs, insnRegCount, getReg, 1274 kRegTypeFloat, pFailure); 1275 actualArgs++; 1276 break; 1277 case 'D': 1278 verifyRegisterType(insnRegs, insnRegCount, getReg, 1279 kRegTypeDoubleLo, pFailure); 1280 actualArgs += 2; 1281 break; 1282 case 'J': 1283 verifyRegisterType(insnRegs, insnRegCount, getReg, 1284 kRegTypeLongLo, pFailure); 1285 actualArgs += 2; 1286 break; 1287 default: 1288 LOG_VFY("VFY: invocation target: bad signature type char '%c'\n", 1289 *sig); 1290 goto bad_sig; 1291 } 1292 1293 sig++; 1294 } 1295 if (*sig != ')') { 1296 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype); 1297 LOG_VFY("VFY: invocation target: bad signature '%s'\n", desc); 1298 free(desc); 1299 goto bad_sig; 1300 } 1301 1302 if (actualArgs != expectedArgs) { 1303 LOG_VFY("VFY: expected %d args, found %d\n", expectedArgs, actualArgs); 1304 goto bad_sig; 1305 } 1306 1307 free(sigOriginal); 1308 return resMethod; 1309 1310 bad_sig: 1311 if (resMethod != NULL) { 1312 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype); 1313 LOG_VFY("VFY: rejecting call to %s.%s %s\n", 1314 resMethod->clazz->descriptor, resMethod->name, desc); 1315 free(desc); 1316 } 1317 1318 fail: 1319 free(sigOriginal); 1320 if (*pFailure == VERIFY_ERROR_NONE) 1321 *pFailure = VERIFY_ERROR_GENERIC; 1322 return NULL; 1323 } 1324 1325 /* 1326 * Get the class object for the type of data stored in a field. This isn't 1327 * stored in the Field struct, so we have to recover it from the signature. 1328 * 1329 * This only works for reference types. Don't call this for primitive types. 1330 * 1331 * If we can't find the class, we return java.lang.Object, so that 1332 * verification can continue if a field is only accessed in trivial ways. 1333 */ 1334 static ClassObject* getFieldClass(const Method* meth, const Field* field) 1335 { 1336 ClassObject* fieldClass; 1337 const char* signature = field->signature; 1338 1339 if ((*signature == 'L') || (*signature == '[')) { 1340 fieldClass = dvmFindClassNoInit(signature, 1341 meth->clazz->classLoader); 1342 } else { 1343 return NULL; 1344 } 1345 1346 if (fieldClass == NULL) { 1347 dvmClearOptException(dvmThreadSelf()); 1348 LOGV("VFY: unable to find class '%s' for field %s.%s, trying Object\n", 1349 field->signature, meth->clazz->descriptor, field->name); 1350 fieldClass = gDvm.classJavaLangObject; 1351 } else { 1352 assert(!dvmIsPrimitiveClass(fieldClass)); 1353 } 1354 return fieldClass; 1355 } 1356 1357 1358 /* 1359 * =========================================================================== 1360 * Register operations 1361 * =========================================================================== 1362 */ 1363 1364 /* 1365 * Get the type of register N, verifying that the register is valid. 1366 * 1367 * Sets "*pFailure" appropriately if the register number is out of range. 1368 */ 1369 static inline RegType getRegisterType(const RegType* insnRegs, 1370 const int insnRegCount, u4 vsrc, VerifyError* pFailure) 1371 { 1372 if (vsrc >= (u4) insnRegCount) { 1373 *pFailure = VERIFY_ERROR_GENERIC; 1374 return kRegTypeUnknown; 1375 } else { 1376 return insnRegs[vsrc]; 1377 } 1378 } 1379 1380 /* 1381 * Get the value from a register, and cast it to a ClassObject. Sets 1382 * "*pFailure" if something fails. 1383 * 1384 * This fails if the register holds an uninitialized class. 1385 * 1386 * If the register holds kRegTypeZero, this returns a NULL pointer. 1387 */ 1388 static ClassObject* getClassFromRegister(const RegType* insnRegs, 1389 const int insnRegCount, u4 vsrc, VerifyError* pFailure) 1390 { 1391 ClassObject* clazz = NULL; 1392 RegType type; 1393 1394 /* get the element type of the array held in vsrc */ 1395 type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure); 1396 if (!VERIFY_OK(*pFailure)) 1397 goto bail; 1398 1399 /* if "always zero", we allow it to fail at runtime */ 1400 if (type == kRegTypeZero) 1401 goto bail; 1402 1403 if (!regTypeIsReference(type)) { 1404 LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n", 1405 vsrc, type); 1406 *pFailure = VERIFY_ERROR_GENERIC; 1407 goto bail; 1408 } 1409 if (regTypeIsUninitReference(type)) { 1410 LOG_VFY("VFY: register %u holds uninitialized reference\n", vsrc); 1411 *pFailure = VERIFY_ERROR_GENERIC; 1412 goto bail; 1413 } 1414 1415 clazz = regTypeInitializedReferenceToClass(type); 1416 1417 bail: 1418 return clazz; 1419 } 1420 1421 /* 1422 * Get the "this" pointer from a non-static method invocation. This 1423 * returns the RegType so the caller can decide whether it needs the 1424 * reference to be initialized or not. (Can also return kRegTypeZero 1425 * if the reference can only be zero at this point.) 1426 * 1427 * The argument count is in vA, and the first argument is in vC, for both 1428 * "simple" and "range" versions. We just need to make sure vA is >= 1 1429 * and then return vC. 1430 */ 1431 static RegType getInvocationThis(const RegType* insnRegs, 1432 const int insnRegCount, const DecodedInstruction* pDecInsn, 1433 VerifyError* pFailure) 1434 { 1435 RegType thisType = kRegTypeUnknown; 1436 1437 if (pDecInsn->vA < 1) { 1438 LOG_VFY("VFY: invoke lacks 'this'\n"); 1439 *pFailure = VERIFY_ERROR_GENERIC; 1440 goto bail; 1441 } 1442 1443 /* get the element type of the array held in vsrc */ 1444 thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pFailure); 1445 if (!VERIFY_OK(*pFailure)) { 1446 LOG_VFY("VFY: failed to get 'this' from register %u\n", pDecInsn->vC); 1447 goto bail; 1448 } 1449 1450 if (!regTypeIsReference(thisType)) { 1451 LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n", 1452 pDecInsn->vC, thisType); 1453 *pFailure = VERIFY_ERROR_GENERIC; 1454 goto bail; 1455 } 1456 1457 bail: 1458 return thisType; 1459 } 1460 1461 /* 1462 * Set the type of register N, verifying that the register is valid. If 1463 * "newType" is the "Lo" part of a 64-bit value, register N+1 will be 1464 * set to "newType+1". 1465 * 1466 * Sets "*pFailure" if the register number is out of range. 1467 */ 1468 static void setRegisterType(RegType* insnRegs, const int insnRegCount, 1469 u4 vdst, RegType newType, VerifyError* pFailure) 1470 { 1471 //LOGD("set-reg v%u = %d\n", vdst, newType); 1472 switch (newType) { 1473 case kRegTypeUnknown: 1474 case kRegTypeBoolean: 1475 case kRegTypeOne: 1476 case kRegTypeByte: 1477 case kRegTypePosByte: 1478 case kRegTypeShort: 1479 case kRegTypePosShort: 1480 case kRegTypeChar: 1481 case kRegTypeInteger: 1482 case kRegTypeFloat: 1483 case kRegTypeZero: 1484 if (vdst >= (u4) insnRegCount) { 1485 *pFailure = VERIFY_ERROR_GENERIC; 1486 } else { 1487 insnRegs[vdst] = newType; 1488 } 1489 break; 1490 case kRegTypeLongLo: 1491 case kRegTypeDoubleLo: 1492 if (vdst+1 >= (u4) insnRegCount) { 1493 *pFailure = VERIFY_ERROR_GENERIC; 1494 } else { 1495 insnRegs[vdst] = newType; 1496 insnRegs[vdst+1] = newType+1; 1497 } 1498 break; 1499 case kRegTypeLongHi: 1500 case kRegTypeDoubleHi: 1501 /* should never set these explicitly */ 1502 *pFailure = VERIFY_ERROR_GENERIC; 1503 break; 1504 1505 case kRegTypeUninit: 1506 default: 1507 if (regTypeIsReference(newType)) { 1508 if (vdst >= (u4) insnRegCount) { 1509 *pFailure = VERIFY_ERROR_GENERIC; 1510 break; 1511 } 1512 insnRegs[vdst] = newType; 1513 1514 /* 1515 * In most circumstances we won't see a reference to a primitive 1516 * class here (e.g. "D"), since that would mean the object in the 1517 * register is actually a primitive type. It can happen as the 1518 * result of an assumed-successful check-cast instruction in 1519 * which the second argument refers to a primitive class. (In 1520 * practice, such an instruction will always throw an exception.) 1521 * 1522 * This is not an issue for instructions like const-class, where 1523 * the object in the register is a java.lang.Class instance. 1524 */ 1525 break; 1526 } 1527 /* bad - fall through */ 1528 1529 case kRegTypeConflict: // should only be set during a merge 1530 LOG_VFY("Unexpected set type %d\n", newType); 1531 assert(false); 1532 *pFailure = VERIFY_ERROR_GENERIC; 1533 break; 1534 } 1535 } 1536 1537 /* 1538 * Verify that the contents of the specified register have the specified 1539 * type (or can be converted to it through an implicit widening conversion). 1540 * 1541 * In theory we could use this to modify the type of the source register, 1542 * e.g. a generic 32-bit constant, once used as a float, would thereafter 1543 * remain a float. There is no compelling reason to require this though. 1544 * 1545 * If "vsrc" is a reference, both it and the "vsrc" register must be 1546 * initialized ("vsrc" may be Zero). This will verify that the value in 1547 * the register is an instance of checkType, or if checkType is an 1548 * interface, verify that the register implements checkType. 1549 */ 1550 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount, 1551 u4 vsrc, RegType checkType, VerifyError* pFailure) 1552 { 1553 if (vsrc >= (u4) insnRegCount) { 1554 *pFailure = VERIFY_ERROR_GENERIC; 1555 return; 1556 } 1557 1558 RegType srcType = insnRegs[vsrc]; 1559 1560 //LOGD("check-reg v%u = %d\n", vsrc, checkType); 1561 switch (checkType) { 1562 case kRegTypeFloat: 1563 case kRegTypeBoolean: 1564 case kRegTypePosByte: 1565 case kRegTypeByte: 1566 case kRegTypePosShort: 1567 case kRegTypeShort: 1568 case kRegTypeChar: 1569 case kRegTypeInteger: 1570 if (!canConvertTo1nr(srcType, checkType)) { 1571 LOG_VFY("VFY: register1 v%u type %d, wanted %d\n", 1572 vsrc, srcType, checkType); 1573 *pFailure = VERIFY_ERROR_GENERIC; 1574 } 1575 break; 1576 case kRegTypeLongLo: 1577 case kRegTypeDoubleLo: 1578 if (vsrc+1 >= (u4) insnRegCount) { 1579 LOG_VFY("VFY: register2 v%u out of range (%d)\n", 1580 vsrc, insnRegCount); 1581 *pFailure = VERIFY_ERROR_GENERIC; 1582 } else if (insnRegs[vsrc+1] != srcType+1) { 1583 LOG_VFY("VFY: register2 v%u-%u values %d,%d\n", 1584 vsrc, vsrc+1, insnRegs[vsrc], insnRegs[vsrc+1]); 1585 *pFailure = VERIFY_ERROR_GENERIC; 1586 } else if (!canConvertTo2(srcType, checkType)) { 1587 LOG_VFY("VFY: register2 v%u type %d, wanted %d\n", 1588 vsrc, srcType, checkType); 1589 *pFailure = VERIFY_ERROR_GENERIC; 1590 } 1591 break; 1592 1593 case kRegTypeLongHi: 1594 case kRegTypeDoubleHi: 1595 case kRegTypeZero: 1596 case kRegTypeOne: 1597 case kRegTypeUnknown: 1598 case kRegTypeConflict: 1599 /* should never be checking for these explicitly */ 1600 assert(false); 1601 *pFailure = VERIFY_ERROR_GENERIC; 1602 return; 1603 case kRegTypeUninit: 1604 default: 1605 /* make sure checkType is initialized reference */ 1606 if (!regTypeIsReference(checkType)) { 1607 LOG_VFY("VFY: unexpected check type %d\n", checkType); 1608 assert(false); 1609 *pFailure = VERIFY_ERROR_GENERIC; 1610 break; 1611 } 1612 if (regTypeIsUninitReference(checkType)) { 1613 LOG_VFY("VFY: uninitialized ref not expected as reg check\n"); 1614 *pFailure = VERIFY_ERROR_GENERIC; 1615 break; 1616 } 1617 /* make sure srcType is initialized reference or always-NULL */ 1618 if (!regTypeIsReference(srcType)) { 1619 LOG_VFY("VFY: register1 v%u type %d, wanted ref\n", vsrc, srcType); 1620 *pFailure = VERIFY_ERROR_GENERIC; 1621 break; 1622 } 1623 if (regTypeIsUninitReference(srcType)) { 1624 LOG_VFY("VFY: register1 v%u holds uninitialized ref\n", vsrc); 1625 *pFailure = VERIFY_ERROR_GENERIC; 1626 break; 1627 } 1628 /* if the register isn't Zero, make sure it's an instance of check */ 1629 if (srcType != kRegTypeZero) { 1630 ClassObject* srcClass = regTypeInitializedReferenceToClass(srcType); 1631 ClassObject* checkClass = regTypeInitializedReferenceToClass(checkType); 1632 assert(srcClass != NULL); 1633 assert(checkClass != NULL); 1634 1635 if (dvmIsInterfaceClass(checkClass)) { 1636 /* 1637 * All objects implement all interfaces as far as the 1638 * verifier is concerned. The runtime has to sort it out. 1639 * See comments above findCommonSuperclass. 1640 */ 1641 /* 1642 if (srcClass != checkClass && 1643 !dvmImplements(srcClass, checkClass)) 1644 { 1645 LOG_VFY("VFY: %s does not implement %s\n", 1646 srcClass->descriptor, checkClass->descriptor); 1647 *pFailure = VERIFY_ERROR_GENERIC; 1648 } 1649 */ 1650 } else { 1651 if (!dvmInstanceof(srcClass, checkClass)) { 1652 LOG_VFY("VFY: %s is not instance of %s\n", 1653 srcClass->descriptor, checkClass->descriptor); 1654 *pFailure = VERIFY_ERROR_GENERIC; 1655 } 1656 } 1657 } 1658 break; 1659 } 1660 } 1661 1662 /* 1663 * Set the type of the "result" register. Mostly this exists to expand 1664 * "insnRegCount" to encompass the result register. 1665 */ 1666 static void setResultRegisterType(RegType* insnRegs, const int insnRegCount, 1667 RegType newType, VerifyError* pFailure) 1668 { 1669 setRegisterType(insnRegs, insnRegCount + kExtraRegs, 1670 RESULT_REGISTER(insnRegCount), newType, pFailure); 1671 } 1672 1673 1674 /* 1675 * Update all registers holding "uninitType" to instead hold the 1676 * corresponding initialized reference type. This is called when an 1677 * appropriate <init> method is invoked -- all copies of the reference 1678 * must be marked as initialized. 1679 */ 1680 static void markRefsAsInitialized(RegType* insnRegs, int insnRegCount, 1681 UninitInstanceMap* uninitMap, RegType uninitType, VerifyError* pFailure) 1682 { 1683 ClassObject* clazz; 1684 RegType initType; 1685 int i, changed; 1686 1687 clazz = dvmGetUninitInstance(uninitMap, regTypeToUninitIndex(uninitType)); 1688 if (clazz == NULL) { 1689 LOGE("VFY: unable to find type=0x%x (idx=%d)\n", 1690 uninitType, regTypeToUninitIndex(uninitType)); 1691 *pFailure = VERIFY_ERROR_GENERIC; 1692 return; 1693 } 1694 initType = regTypeFromClass(clazz); 1695 1696 changed = 0; 1697 for (i = 0; i < insnRegCount; i++) { 1698 if (insnRegs[i] == uninitType) { 1699 insnRegs[i] = initType; 1700 changed++; 1701 } 1702 } 1703 //LOGD("VFY: marked %d registers as initialized\n", changed); 1704 assert(changed > 0); 1705 1706 return; 1707 } 1708 1709 /* 1710 * We're creating a new instance of class C at address A. Any registers 1711 * holding instances previously created at address A must be initialized 1712 * by now. If not, we mark them as "conflict" to prevent them from being 1713 * used (otherwise, markRefsAsInitialized would mark the old ones and the 1714 * new ones at the same time). 1715 */ 1716 static void markUninitRefsAsInvalid(RegType* insnRegs, int insnRegCount, 1717 UninitInstanceMap* uninitMap, RegType uninitType) 1718 { 1719 int i, changed; 1720 1721 changed = 0; 1722 for (i = 0; i < insnRegCount; i++) { 1723 if (insnRegs[i] == uninitType) { 1724 insnRegs[i] = kRegTypeConflict; 1725 changed++; 1726 } 1727 } 1728 1729 //if (changed) 1730 // LOGD("VFY: marked %d uninitialized registers as invalid\n", changed); 1731 } 1732 1733 /* 1734 * Find the start of the register set for the specified instruction in 1735 * the current method. 1736 */ 1737 static inline RegType* getRegisterLine(const RegisterTable* regTable, 1738 int insnIdx) 1739 { 1740 return regTable->addrRegs[insnIdx]; 1741 } 1742 1743 /* 1744 * Copy a bunch of registers. 1745 */ 1746 static inline void copyRegisters(RegType* dst, const RegType* src, 1747 int numRegs) 1748 { 1749 memcpy(dst, src, numRegs * sizeof(RegType)); 1750 } 1751 1752 /* 1753 * Compare a bunch of registers. 1754 * 1755 * Returns 0 if they match. Using this for a sort is unwise, since the 1756 * value can change based on machine endianness. 1757 */ 1758 static inline int compareRegisters(const RegType* src1, const RegType* src2, 1759 int numRegs) 1760 { 1761 return memcmp(src1, src2, numRegs * sizeof(RegType)); 1762 } 1763 1764 /* 1765 * Register type categories, for type checking. 1766 * 1767 * The spec says category 1 includes boolean, byte, char, short, int, float, 1768 * reference, and returnAddress. Category 2 includes long and double. 1769 * 1770 * We treat object references separately, so we have "category1nr". We 1771 * don't support jsr/ret, so there is no "returnAddress" type. 1772 */ 1773 typedef enum TypeCategory { 1774 kTypeCategoryUnknown = 0, 1775 kTypeCategory1nr, // byte, char, int, float, boolean 1776 kTypeCategory2, // long, double 1777 kTypeCategoryRef, // object reference 1778 } TypeCategory; 1779 1780 /* 1781 * See if "type" matches "cat". All we're really looking for here is that 1782 * we're not mixing and matching 32-bit and 64-bit quantities, and we're 1783 * not mixing references with numerics. (For example, the arguments to 1784 * "a < b" could be integers of different sizes, but they must both be 1785 * integers. Dalvik is less specific about int vs. float, so we treat them 1786 * as equivalent here.) 1787 * 1788 * For category 2 values, "type" must be the "low" half of the value. 1789 * 1790 * Sets "*pFailure" if something looks wrong. 1791 */ 1792 static void checkTypeCategory(RegType type, TypeCategory cat, 1793 VerifyError* pFailure) 1794 { 1795 switch (cat) { 1796 case kTypeCategory1nr: 1797 switch (type) { 1798 case kRegTypeFloat: 1799 case kRegTypeZero: 1800 case kRegTypeOne: 1801 case kRegTypeBoolean: 1802 case kRegTypePosByte: 1803 case kRegTypeByte: 1804 case kRegTypePosShort: 1805 case kRegTypeShort: 1806 case kRegTypeChar: 1807 case kRegTypeInteger: 1808 break; 1809 default: 1810 *pFailure = VERIFY_ERROR_GENERIC; 1811 break; 1812 } 1813 break; 1814 1815 case kTypeCategory2: 1816 switch (type) { 1817 case kRegTypeLongLo: 1818 case kRegTypeDoubleLo: 1819 break; 1820 default: 1821 *pFailure = VERIFY_ERROR_GENERIC; 1822 break; 1823 } 1824 break; 1825 1826 case kTypeCategoryRef: 1827 if (type != kRegTypeZero && !regTypeIsReference(type)) 1828 *pFailure = VERIFY_ERROR_GENERIC; 1829 break; 1830 1831 default: 1832 assert(false); 1833 *pFailure = VERIFY_ERROR_GENERIC; 1834 break; 1835 } 1836 } 1837 1838 /* 1839 * For a category 2 register pair, verify that "typeh" is the appropriate 1840 * high part for "typel". 1841 * 1842 * Does not verify that "typel" is in fact the low part of a 64-bit 1843 * register pair. 1844 */ 1845 static void checkWidePair(RegType typel, RegType typeh, VerifyError* pFailure) 1846 { 1847 if ((typeh != typel+1)) 1848 *pFailure = VERIFY_ERROR_GENERIC; 1849 } 1850 1851 /* 1852 * Implement category-1 "move" instructions. Copy a 32-bit value from 1853 * "vsrc" to "vdst". 1854 * 1855 * "insnRegCount" is the number of registers available. The "vdst" and 1856 * "vsrc" values are checked against this. 1857 */ 1858 static void copyRegister1(RegType* insnRegs, int insnRegCount, u4 vdst, 1859 u4 vsrc, TypeCategory cat, VerifyError* pFailure) 1860 { 1861 RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure); 1862 if (VERIFY_OK(*pFailure)) 1863 checkTypeCategory(type, cat, pFailure); 1864 if (VERIFY_OK(*pFailure)) 1865 setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure); 1866 1867 if (!VERIFY_OK(*pFailure)) { 1868 LOG_VFY("VFY: copy1 v%u<-v%u type=%d cat=%d\n", vdst, vsrc, type, cat); 1869 } 1870 } 1871 1872 /* 1873 * Implement category-2 "move" instructions. Copy a 64-bit value from 1874 * "vsrc" to "vdst". This copies both halves of the register. 1875 */ 1876 static void copyRegister2(RegType* insnRegs, int insnRegCount, u4 vdst, 1877 u4 vsrc, VerifyError* pFailure) 1878 { 1879 RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure); 1880 RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pFailure); 1881 if (VERIFY_OK(*pFailure)) { 1882 checkTypeCategory(typel, kTypeCategory2, pFailure); 1883 checkWidePair(typel, typeh, pFailure); 1884 } 1885 if (VERIFY_OK(*pFailure)) 1886 setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure); 1887 1888 if (!VERIFY_OK(*pFailure)) { 1889 LOG_VFY("VFY: copy2 v%u<-v%u type=%d/%d\n", vdst, vsrc, typel, typeh); 1890 } 1891 } 1892 1893 /* 1894 * Implement "move-result". Copy the category-1 value from the result 1895 * register to another register, and reset the result register. 1896 * 1897 * We can't just call copyRegister1 with an altered insnRegCount, 1898 * because that would affect the test on "vdst" as well. 1899 */ 1900 static void copyResultRegister1(RegType* insnRegs, const int insnRegCount, 1901 u4 vdst, TypeCategory cat, VerifyError* pFailure) 1902 { 1903 RegType type; 1904 u4 vsrc; 1905 1906 vsrc = RESULT_REGISTER(insnRegCount); 1907 type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pFailure); 1908 if (VERIFY_OK(*pFailure)) 1909 checkTypeCategory(type, cat, pFailure); 1910 if (VERIFY_OK(*pFailure)) { 1911 setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure); 1912 insnRegs[vsrc] = kRegTypeUnknown; 1913 } 1914 1915 if (!VERIFY_OK(*pFailure)) { 1916 LOG_VFY("VFY: copyRes1 v%u<-v%u cat=%d type=%d\n", 1917 vdst, vsrc, cat, type); 1918 } 1919 } 1920 1921 /* 1922 * Implement "move-result-wide". Copy the category-2 value from the result 1923 * register to another register, and reset the result register. 1924 * 1925 * We can't just call copyRegister2 with an altered insnRegCount, 1926 * because that would affect the test on "vdst" as well. 1927 */ 1928 static void copyResultRegister2(RegType* insnRegs, const int insnRegCount, 1929 u4 vdst, VerifyError* pFailure) 1930 { 1931 RegType typel, typeh; 1932 u4 vsrc; 1933 1934 vsrc = RESULT_REGISTER(insnRegCount); 1935 typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, 1936 pFailure); 1937 typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1, 1938 pFailure); 1939 if (VERIFY_OK(*pFailure)) { 1940 checkTypeCategory(typel, kTypeCategory2, pFailure); 1941 checkWidePair(typel, typeh, pFailure); 1942 } 1943 if (VERIFY_OK(*pFailure)) { 1944 setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure); 1945 insnRegs[vsrc] = kRegTypeUnknown; 1946 insnRegs[vsrc+1] = kRegTypeUnknown; 1947 } 1948 1949 if (!VERIFY_OK(*pFailure)) { 1950 LOG_VFY("VFY: copyRes2 v%u<-v%u type=%d/%d\n", 1951 vdst, vsrc, typel, typeh); 1952 } 1953 } 1954 1955 /* 1956 * Verify types for a simple two-register instruction (e.g. "neg-int"). 1957 * "dstType" is stored into vA, and "srcType" is verified against vB. 1958 */ 1959 static void checkUnop(RegType* insnRegs, const int insnRegCount, 1960 DecodedInstruction* pDecInsn, RegType dstType, RegType srcType, 1961 VerifyError* pFailure) 1962 { 1963 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure); 1964 setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure); 1965 } 1966 1967 /* 1968 * We're performing an operation like "and-int/2addr" that can be 1969 * performed on booleans as well as integers. We get no indication of 1970 * boolean-ness, but we can infer it from the types of the arguments. 1971 * 1972 * Assumes we've already validated reg1/reg2. 1973 * 1974 * TODO: consider generalizing this. The key principle is that the 1975 * result of a bitwise operation can only be as wide as the widest of 1976 * the operands. You can safely AND/OR/XOR two chars together and know 1977 * you still have a char, so it's reasonable for the compiler or "dx" 1978 * to skip the int-to-char instruction. (We need to do this for boolean 1979 * because there is no int-to-boolean operation.) 1980 * 1981 * Returns true if both args are Boolean, Zero, or One. 1982 */ 1983 static bool upcastBooleanOp(RegType* insnRegs, const int insnRegCount, 1984 u4 reg1, u4 reg2) 1985 { 1986 RegType type1, type2; 1987 1988 type1 = insnRegs[reg1]; 1989 type2 = insnRegs[reg2]; 1990 1991 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero || 1992 type1 == kRegTypeOne) && 1993 (type2 == kRegTypeBoolean || type2 == kRegTypeZero || 1994 type2 == kRegTypeOne)) 1995 { 1996 return true; 1997 } 1998 return false; 1999 } 2000 2001 /* 2002 * Verify types for A two-register instruction with a literal constant 2003 * (e.g. "add-int/lit8"). "dstType" is stored into vA, and "srcType" is 2004 * verified against vB. 2005 * 2006 * If "checkBooleanOp" is set, we use the constant value in vC. 2007 */ 2008 static void checkLitop(RegType* insnRegs, const int insnRegCount, 2009 DecodedInstruction* pDecInsn, RegType dstType, RegType srcType, 2010 bool checkBooleanOp, VerifyError* pFailure) 2011 { 2012 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure); 2013 if (VERIFY_OK(*pFailure) && checkBooleanOp) { 2014 assert(dstType == kRegTypeInteger); 2015 /* check vB with the call, then check the constant manually */ 2016 if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vB) 2017 && (pDecInsn->vC == 0 || pDecInsn->vC == 1)) 2018 { 2019 dstType = kRegTypeBoolean; 2020 } 2021 } 2022 setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure); 2023 } 2024 2025 /* 2026 * Verify types for a simple three-register instruction (e.g. "add-int"). 2027 * "dstType" is stored into vA, and "srcType1"/"srcType2" are verified 2028 * against vB/vC. 2029 */ 2030 static void checkBinop(RegType* insnRegs, const int insnRegCount, 2031 DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1, 2032 RegType srcType2, bool checkBooleanOp, VerifyError* pFailure) 2033 { 2034 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1, 2035 pFailure); 2036 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2, 2037 pFailure); 2038 if (VERIFY_OK(*pFailure) && checkBooleanOp) { 2039 assert(dstType == kRegTypeInteger); 2040 if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vC)) 2041 dstType = kRegTypeBoolean; 2042 } 2043 setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure); 2044 } 2045 2046 /* 2047 * Verify types for a binary "2addr" operation. "srcType1"/"srcType2" 2048 * are verified against vA/vB, then "dstType" is stored into vA. 2049 */ 2050 static void checkBinop2addr(RegType* insnRegs, const int insnRegCount, 2051 DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1, 2052 RegType srcType2, bool checkBooleanOp, VerifyError* pFailure) 2053 { 2054 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1, 2055 pFailure); 2056 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2, 2057 pFailure); 2058 if (VERIFY_OK(*pFailure) && checkBooleanOp) { 2059 assert(dstType == kRegTypeInteger); 2060 if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vA, pDecInsn->vB)) 2061 dstType = kRegTypeBoolean; 2062 } 2063 setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure); 2064 } 2065 2066 /* 2067 * Treat right-shifting as a narrowing conversion when possible. 2068 * 2069 * For example, right-shifting an int 24 times results in a value that can 2070 * be treated as a byte. 2071 * 2072 * Things get interesting when contemplating sign extension. Right- 2073 * shifting an integer by 16 yields a value that can be represented in a 2074 * "short" but not a "char", but an unsigned right shift by 16 yields a 2075 * value that belongs in a char rather than a short. (Consider what would 2076 * happen if the result of the shift were cast to a char or short and then 2077 * cast back to an int. If sign extension, or the lack thereof, causes 2078 * a change in the 32-bit representation, then the conversion was lossy.) 2079 * 2080 * A signed right shift by 17 on an integer results in a short. An unsigned 2081 * right shfit by 17 on an integer results in a posshort, which can be 2082 * assigned to a short or a char. 2083 * 2084 * An unsigned right shift on a short can actually expand the result into 2085 * a 32-bit integer. For example, 0xfffff123 >>> 8 becomes 0x00fffff1, 2086 * which can't be represented in anything smaller than an int. 2087 * 2088 * javac does not generate code that takes advantage of this, but some 2089 * of the code optimizers do. It's generally a peephole optimization 2090 * that replaces a particular sequence, e.g. (bipush 24, ishr, i2b) is 2091 * replaced by (bipush 24, ishr). Knowing that shifting a short 8 times 2092 * to the right yields a byte is really more than we need to handle the 2093 * code that's out there, but support is not much more complex than just 2094 * handling integer. 2095 * 2096 * Right-shifting never yields a boolean value. 2097 * 2098 * Returns the new register type. 2099 */ 2100 static RegType adjustForRightShift(RegType* workRegs, const int insnRegCount, 2101 int reg, unsigned int shiftCount, bool isUnsignedShift, 2102 VerifyError* pFailure) 2103 { 2104 RegType srcType = getRegisterType(workRegs, insnRegCount, reg, pFailure); 2105 RegType newType; 2106 2107 /* no-op */ 2108 if (shiftCount == 0) 2109 return srcType; 2110 2111 /* safe defaults */ 2112 if (isUnsignedShift) 2113 newType = kRegTypeInteger; 2114 else 2115 newType = srcType; 2116 2117 if (shiftCount >= 32) { 2118 LOG_VFY("Got unexpectedly large shift count %u\n", shiftCount); 2119 /* fail? */ 2120 return newType; 2121 } 2122 2123 switch (srcType) { 2124 case kRegTypeInteger: /* 32-bit signed value */ 2125 case kRegTypeFloat: /* (allowed; treat same as int) */ 2126 if (isUnsignedShift) { 2127 if (shiftCount > 24) 2128 newType = kRegTypePosByte; 2129 else if (shiftCount >= 16) 2130 newType = kRegTypeChar; 2131 } else { 2132 if (shiftCount >= 24) 2133 newType = kRegTypeByte; 2134 else if (shiftCount >= 16) 2135 newType = kRegTypeShort; 2136 } 2137 break; 2138 case kRegTypeShort: /* 16-bit signed value */ 2139 if (isUnsignedShift) { 2140 /* default (kRegTypeInteger) is correct */ 2141 } else { 2142 if (shiftCount >= 8) 2143 newType = kRegTypeByte; 2144 } 2145 break; 2146 case kRegTypePosShort: /* 15-bit unsigned value */ 2147 if (shiftCount >= 8) 2148 newType = kRegTypePosByte; 2149 break; 2150 case kRegTypeChar: /* 16-bit unsigned value */ 2151 if (shiftCount > 8) 2152 newType = kRegTypePosByte; 2153 break; 2154 case kRegTypeByte: /* 8-bit signed value */ 2155 /* defaults (u=kRegTypeInteger / s=srcType) are correct */ 2156 break; 2157 case kRegTypePosByte: /* 7-bit unsigned value */ 2158 /* always use newType=srcType */ 2159 newType = srcType; 2160 break; 2161 case kRegTypeZero: /* 1-bit unsigned value */ 2162 case kRegTypeOne: 2163 case kRegTypeBoolean: 2164 /* unnecessary? */ 2165 newType = kRegTypeZero; 2166 break; 2167 default: 2168 /* long, double, references; shouldn't be here! */ 2169 assert(false); 2170 break; 2171 } 2172 2173 if (newType != srcType) { 2174 LOGVV("narrowing: %d(%d) --> %d to %d\n", 2175 shiftCount, isUnsignedShift, srcType, newType); 2176 } else { 2177 LOGVV("not narrowed: %d(%d) --> %d\n", 2178 shiftCount, isUnsignedShift, srcType); 2179 } 2180 return newType; 2181 } 2182 2183 2184 /* 2185 * =========================================================================== 2186 * Register merge 2187 * =========================================================================== 2188 */ 2189 2190 /* 2191 * Compute the "class depth" of a class. This is the distance from the 2192 * class to the top of the tree, chasing superclass links. java.lang.Object 2193 * has a class depth of 0. 2194 */ 2195 static int getClassDepth(ClassObject* clazz) 2196 { 2197 int depth = 0; 2198 2199 while (clazz->super != NULL) { 2200 clazz = clazz->super; 2201 depth++; 2202 } 2203 return depth; 2204 } 2205 2206 /* 2207 * Given two classes, walk up the superclass tree to find a common 2208 * ancestor. (Called from findCommonSuperclass().) 2209 * 2210 * TODO: consider caching the class depth in the class object so we don't 2211 * have to search for it here. 2212 */ 2213 static ClassObject* digForSuperclass(ClassObject* c1, ClassObject* c2) 2214 { 2215 int depth1, depth2; 2216 2217 depth1 = getClassDepth(c1); 2218 depth2 = getClassDepth(c2); 2219 2220 if (gDebugVerbose) { 2221 LOGVV("COMMON: %s(%d) + %s(%d)\n", 2222 c1->descriptor, depth1, c2->descriptor, depth2); 2223 } 2224 2225 /* pull the deepest one up */ 2226 if (depth1 > depth2) { 2227 while (depth1 > depth2) { 2228 c1 = c1->super; 2229 depth1--; 2230 } 2231 } else { 2232 while (depth2 > depth1) { 2233 c2 = c2->super; 2234 depth2--; 2235 } 2236 } 2237 2238 /* walk up in lock-step */ 2239 while (c1 != c2) { 2240 c1 = c1->super; 2241 c2 = c2->super; 2242 2243 assert(c1 != NULL && c2 != NULL); 2244 } 2245 2246 if (gDebugVerbose) { 2247 LOGVV(" : --> %s\n", c1->descriptor); 2248 } 2249 return c1; 2250 } 2251 2252 /* 2253 * Merge two array classes. We can't use the general "walk up to the 2254 * superclass" merge because the superclass of an array is always Object. 2255 * We want String[] + Integer[] = Object[]. This works for higher dimensions 2256 * as well, e.g. String[][] + Integer[][] = Object[][]. 2257 * 2258 * If Foo1 and Foo2 are subclasses of Foo, Foo1[] + Foo2[] = Foo[]. 2259 * 2260 * If Class implements Type, Class[] + Type[] = Type[]. 2261 * 2262 * If the dimensions don't match, we want to convert to an array of Object 2263 * with the least dimension, e.g. String[][] + String[][][][] = Object[][]. 2264 * 2265 * This gets a little awkward because we may have to ask the VM to create 2266 * a new array type with the appropriate element and dimensions. However, we 2267 * shouldn't be doing this often. 2268 */ 2269 static ClassObject* findCommonArraySuperclass(ClassObject* c1, ClassObject* c2) 2270 { 2271 ClassObject* arrayClass = NULL; 2272 ClassObject* commonElem; 2273 int i, numDims; 2274 2275 assert(c1->arrayDim > 0); 2276 assert(c2->arrayDim > 0); 2277 2278 if (c1->arrayDim == c2->arrayDim) { 2279 //commonElem = digForSuperclass(c1->elementClass, c2->elementClass); 2280 commonElem = findCommonSuperclass(c1->elementClass, c2->elementClass); 2281 numDims = c1->arrayDim; 2282 } else { 2283 if (c1->arrayDim < c2->arrayDim) 2284 numDims = c1->arrayDim; 2285 else 2286 numDims = c2->arrayDim; 2287 commonElem = c1->super; // == java.lang.Object 2288 } 2289 2290 /* walk from the element to the (multi-)dimensioned array type */ 2291 for (i = 0; i < numDims; i++) { 2292 arrayClass = dvmFindArrayClassForElement(commonElem); 2293 commonElem = arrayClass; 2294 } 2295 2296 LOGVV("ArrayMerge '%s' + '%s' --> '%s'\n", 2297 c1->descriptor, c2->descriptor, arrayClass->descriptor); 2298 return arrayClass; 2299 } 2300 2301 /* 2302 * Find the first common superclass of the two classes. We're not 2303 * interested in common interfaces. 2304 * 2305 * The easiest way to do this for concrete classes is to compute the "class 2306 * depth" of each, move up toward the root of the deepest one until they're 2307 * at the same depth, then walk both up to the root until they match. 2308 * 2309 * If both classes are arrays of non-primitive types, we need to merge 2310 * based on array depth and element type. 2311 * 2312 * If one class is an interface, we check to see if the other class/interface 2313 * (or one of its predecessors) implements the interface. If so, we return 2314 * the interface; otherwise, we return Object. 2315 * 2316 * NOTE: we continue the tradition of "lazy interface handling". To wit, 2317 * suppose we have three classes: 2318 * One implements Fancy, Free 2319 * Two implements Fancy, Free 2320 * Three implements Free 2321 * where Fancy and Free are unrelated interfaces. The code requires us 2322 * to merge One into Two. Ideally we'd use a common interface, which 2323 * gives us a choice between Fancy and Free, and no guidance on which to 2324 * use. If we use Free, we'll be okay when Three gets merged in, but if 2325 * we choose Fancy, we're hosed. The "ideal" solution is to create a 2326 * set of common interfaces and carry that around, merging further references 2327 * into it. This is a pain. The easy solution is to simply boil them 2328 * down to Objects and let the runtime invokeinterface call fail, which 2329 * is what we do. 2330 */ 2331 static ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2) 2332 { 2333 assert(!dvmIsPrimitiveClass(c1) && !dvmIsPrimitiveClass(c2)); 2334 2335 if (c1 == c2) 2336 return c1; 2337 2338 if (dvmIsInterfaceClass(c1) && dvmImplements(c2, c1)) { 2339 if (gDebugVerbose) 2340 LOGVV("COMMON/I1: %s + %s --> %s\n", 2341 c1->descriptor, c2->descriptor, c1->descriptor); 2342 return c1; 2343 } 2344 if (dvmIsInterfaceClass(c2) && dvmImplements(c1, c2)) { 2345 if (gDebugVerbose) 2346 LOGVV("COMMON/I2: %s + %s --> %s\n", 2347 c1->descriptor, c2->descriptor, c2->descriptor); 2348 return c2; 2349 } 2350 2351 if (dvmIsArrayClass(c1) && dvmIsArrayClass(c2) && 2352 !dvmIsPrimitiveClass(c1->elementClass) && 2353 !dvmIsPrimitiveClass(c2->elementClass)) 2354 { 2355 return findCommonArraySuperclass(c1, c2); 2356 } 2357 2358 return digForSuperclass(c1, c2); 2359 } 2360 2361 /* 2362 * Merge two RegType values. 2363 * 2364 * Sets "*pChanged" to "true" if the result doesn't match "type1". 2365 */ 2366 static RegType mergeTypes(RegType type1, RegType type2, bool* pChanged) 2367 { 2368 RegType result; 2369 2370 /* 2371 * Check for trivial case so we don't have to hit memory. 2372 */ 2373 if (type1 == type2) 2374 return type1; 2375 2376 /* 2377 * Use the table if we can, and reject any attempts to merge something 2378 * from the table with a reference type. 2379 * 2380 * The uninitialized table entry at index zero *will* show up as a 2381 * simple kRegTypeUninit value. Since this cannot be merged with 2382 * anything but itself, the rules do the right thing. 2383 */ 2384 if (type1 < kRegTypeMAX) { 2385 if (type2 < kRegTypeMAX) { 2386 result = gDvmMergeTab[type1][type2]; 2387 } else { 2388 /* simple + reference == conflict, usually */ 2389 if (type1 == kRegTypeZero) 2390 result = type2; 2391 else 2392 result = kRegTypeConflict; 2393 } 2394 } else { 2395 if (type2 < kRegTypeMAX) { 2396 /* reference + simple == conflict, usually */ 2397 if (type2 == kRegTypeZero) 2398 result = type1; 2399 else 2400 result = kRegTypeConflict; 2401 } else { 2402 /* merging two references */ 2403 if (regTypeIsUninitReference(type1) || 2404 regTypeIsUninitReference(type2)) 2405 { 2406 /* can't merge uninit with anything but self */ 2407 result = kRegTypeConflict; 2408 } else { 2409 ClassObject* clazz1 = regTypeInitializedReferenceToClass(type1); 2410 ClassObject* clazz2 = regTypeInitializedReferenceToClass(type2); 2411 ClassObject* mergedClass; 2412 2413 mergedClass = findCommonSuperclass(clazz1, clazz2); 2414 assert(mergedClass != NULL); 2415 result = regTypeFromClass(mergedClass); 2416 } 2417 } 2418 } 2419 2420 if (result != type1) 2421 *pChanged = true; 2422 return result; 2423 } 2424 2425 /* 2426 * Control can transfer to "nextInsn". 2427 * 2428 * Merge the registers from "workRegs" into "regTypes" at "nextInsn", and 2429 * set the "changed" flag on the target address if the registers have changed. 2430 */ 2431 static void updateRegisters(const Method* meth, InsnFlags* insnFlags, 2432 RegisterTable* regTable, int nextInsn, const RegType* workRegs) 2433 { 2434 RegType* targetRegs = getRegisterLine(regTable, nextInsn); 2435 const int insnRegCount = meth->registersSize; 2436 2437 #if 0 2438 if (!dvmInsnIsBranchTarget(insnFlags, nextInsn)) { 2439 LOGE("insnFlags[0x%x]=0x%08x\n", nextInsn, insnFlags[nextInsn]); 2440 LOGE(" In %s.%s %s\n", 2441 meth->clazz->descriptor, meth->name, meth->descriptor); 2442 assert(false); 2443 } 2444 #endif 2445 2446 if (!dvmInsnIsVisitedOrChanged(insnFlags, nextInsn)) { 2447 /* 2448 * We haven't processed this instruction before, and we haven't 2449 * touched the registers here, so there's nothing to "merge". Copy 2450 * the registers over and mark it as changed. (This is the only 2451 * way a register can transition out of "unknown", so this is not 2452 * just an optimization.) 2453 */ 2454 LOGVV("COPY into 0x%04x\n", nextInsn); 2455 copyRegisters(targetRegs, workRegs, insnRegCount + kExtraRegs); 2456 dvmInsnSetChanged(insnFlags, nextInsn, true); 2457 } else { 2458 if (gDebugVerbose) { 2459 LOGVV("MERGE into 0x%04x\n", nextInsn); 2460 //dumpRegTypes(meth, insnFlags, targetRegs, 0, "targ", NULL, 0); 2461 //dumpRegTypes(meth, insnFlags, workRegs, 0, "work", NULL, 0); 2462 } 2463 /* merge registers, set Changed only if different */ 2464 bool changed = false; 2465 int i; 2466 2467 for (i = 0; i < insnRegCount + kExtraRegs; i++) { 2468 targetRegs[i] = mergeTypes(targetRegs[i], workRegs[i], &changed); 2469 } 2470 2471 if (gDebugVerbose) { 2472 //LOGI(" RESULT (changed=%d)\n", changed); 2473 //dumpRegTypes(meth, insnFlags, targetRegs, 0, "rslt", NULL, 0); 2474 } 2475 2476 if (changed) 2477 dvmInsnSetChanged(insnFlags, nextInsn, true); 2478 } 2479 } 2480 2481 2482 /* 2483 * =========================================================================== 2484 * Utility functions 2485 * =========================================================================== 2486 */ 2487 2488 /* 2489 * Look up an instance field, specified by "fieldIdx", that is going to be 2490 * accessed in object "objType". This resolves the field and then verifies 2491 * that the class containing the field is an instance of the reference in 2492 * "objType". 2493 * 2494 * It is possible for "objType" to be kRegTypeZero, meaning that we might 2495 * have a null reference. This is a runtime problem, so we allow it, 2496 * skipping some of the type checks. 2497 * 2498 * In general, "objType" must be an initialized reference. However, we 2499 * allow it to be uninitialized if this is an "<init>" method and the field 2500 * is declared within the "objType" class. 2501 * 2502 * Returns an InstField on success, returns NULL and sets "*pFailure" 2503 * on failure. 2504 */ 2505 static InstField* getInstField(const Method* meth, 2506 const UninitInstanceMap* uninitMap, RegType objType, int fieldIdx, 2507 VerifyError* pFailure) 2508 { 2509 InstField* instField = NULL; 2510 ClassObject* objClass; 2511 bool mustBeLocal = false; 2512 2513 if (!regTypeIsReference(objType)) { 2514 LOG_VFY("VFY: attempt to access field in non-reference type %d\n", 2515 objType); 2516 *pFailure = VERIFY_ERROR_GENERIC; 2517 goto bail; 2518 } 2519 2520 instField = dvmOptResolveInstField(meth->clazz, fieldIdx, pFailure); 2521 if (instField == NULL) { 2522 LOG_VFY("VFY: unable to resolve instance field %u\n", fieldIdx); 2523 assert(!VERIFY_OK(*pFailure)); 2524 goto bail; 2525 } 2526 2527 if (objType == kRegTypeZero) 2528 goto bail; 2529 2530 /* 2531 * Access to fields in uninitialized objects is allowed if this is 2532 * the <init> method for the object and the field in question is 2533 * declared by this class. 2534 */ 2535 objClass = regTypeReferenceToClass(objType, uninitMap); 2536 assert(objClass != NULL); 2537 if (regTypeIsUninitReference(objType)) { 2538 if (!isInitMethod(meth) || meth->clazz != objClass) { 2539 LOG_VFY("VFY: attempt to access field via uninitialized ref\n"); 2540 *pFailure = VERIFY_ERROR_GENERIC; 2541 goto bail; 2542 } 2543 mustBeLocal = true; 2544 } 2545 2546 if (!dvmInstanceof(objClass, instField->field.clazz)) { 2547 LOG_VFY("VFY: invalid field access (field %s.%s, through %s ref)\n", 2548 instField->field.clazz->descriptor, instField->field.name, 2549 objClass->descriptor); 2550 *pFailure = VERIFY_ERROR_NO_FIELD; 2551 goto bail; 2552 } 2553 2554 if (mustBeLocal) { 2555 /* for uninit ref, make sure it's defined by this class, not super */ 2556 if (instField < objClass->ifields || 2557 instField >= objClass->ifields + objClass->ifieldCount) 2558 { 2559 LOG_VFY("VFY: invalid constructor field access (field %s in %s)\n", 2560 instField->field.name, objClass->descriptor); 2561 *pFailure = VERIFY_ERROR_GENERIC; 2562 goto bail; 2563 } 2564 } 2565 2566 bail: 2567 return instField; 2568 } 2569 2570 /* 2571 * Look up a static field. 2572 * 2573 * Returns a StaticField on success, returns NULL and sets "*pFailure" 2574 * on failure. 2575 */ 2576 static StaticField* getStaticField(const Method* meth, int fieldIdx, 2577 VerifyError* pFailure) 2578 { 2579 StaticField* staticField; 2580 2581 staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx, pFailure); 2582 if (staticField == NULL) { 2583 DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile; 2584 const DexFieldId* pFieldId; 2585 2586 pFieldId = dexGetFieldId(pDexFile, fieldIdx); 2587 2588 LOG_VFY("VFY: unable to resolve static field %u (%s) in %s\n", fieldIdx, 2589 dexStringById(pDexFile, pFieldId->nameIdx), 2590 dexStringByTypeIdx(pDexFile, pFieldId->classIdx)); 2591 assert(!VERIFY_OK(*pFailure)); 2592 goto bail; 2593 } 2594 2595 bail: 2596 return staticField; 2597 } 2598 2599 /* 2600 * If "field" is marked "final", make sure this is the either <clinit> 2601 * or <init> as appropriate. 2602 * 2603 * Sets "*pFailure" on failure. 2604 */ 2605 static void checkFinalFieldAccess(const Method* meth, const Field* field, 2606 VerifyError* pFailure) 2607 { 2608 if (!dvmIsFinalField(field)) 2609 return; 2610 2611 /* make sure we're in the same class */ 2612 if (meth->clazz != field->clazz) { 2613 LOG_VFY_METH(meth, "VFY: can't modify final field %s.%s\n", 2614 field->clazz->descriptor, field->name); 2615 *pFailure = VERIFY_ERROR_ACCESS_FIELD; 2616 return; 2617 } 2618 2619 /* 2620 * The VM spec descriptions of putfield and putstatic say that 2621 * IllegalAccessError is only thrown when the instructions appear 2622 * outside the declaring class. Our earlier attempts to restrict 2623 * final field modification to constructors are, therefore, wrong. 2624 */ 2625 #if 0 2626 /* make sure we're in the right kind of constructor */ 2627 if (dvmIsStaticField(field)) { 2628 if (!isClassInitMethod(meth)) { 2629 LOG_VFY_METH(meth, 2630 "VFY: can't modify final static field outside <clinit>\n"); 2631 *pFailure = VERIFY_ERROR_GENERIC; 2632 } 2633 } else { 2634 if (!isInitMethod(meth)) { 2635 LOG_VFY_METH(meth, 2636 "VFY: can't modify final field outside <init>\n"); 2637 *pFailure = VERIFY_ERROR_GENERIC; 2638 } 2639 } 2640 #endif 2641 } 2642 2643 /* 2644 * Make sure that the register type is suitable for use as an array index. 2645 * 2646 * Sets "*pFailure" if not. 2647 */ 2648 static void checkArrayIndexType(const Method* meth, RegType regType, 2649 VerifyError* pFailure) 2650 { 2651 if (VERIFY_OK(*pFailure)) { 2652 /* 2653 * The 1nr types are interchangeable at this level. We could 2654 * do something special if we can definitively identify it as a 2655 * float, but there's no real value in doing so. 2656 */ 2657 checkTypeCategory(regType, kTypeCategory1nr, pFailure); 2658 if (!VERIFY_OK(*pFailure)) { 2659 LOG_VFY_METH(meth, "Invalid reg type for array index (%d)\n", 2660 regType); 2661 } 2662 } 2663 } 2664 2665 /* 2666 * Check constraints on constructor return. Specifically, make sure that 2667 * the "this" argument got initialized. 2668 * 2669 * The "this" argument to <init> uses code offset kUninitThisArgAddr, which 2670 * puts it at the start of the list in slot 0. If we see a register with 2671 * an uninitialized slot 0 reference, we know it somehow didn't get 2672 * initialized. 2673 * 2674 * Returns "true" if all is well. 2675 */ 2676 static bool checkConstructorReturn(const Method* meth, const RegType* insnRegs, 2677 const int insnRegCount) 2678 { 2679 int i; 2680 2681 if (!isInitMethod(meth)) 2682 return true; 2683 2684 RegType uninitThis = regTypeFromUninitIndex(kUninitThisArgSlot); 2685 2686 for (i = 0; i < insnRegCount; i++) { 2687 if (insnRegs[i] == uninitThis) { 2688 LOG_VFY("VFY: <init> returning without calling superclass init\n"); 2689 return false; 2690 } 2691 } 2692 return true; 2693 } 2694 2695 /* 2696 * Verify that the target instruction is not "move-exception". It's important 2697 * that the only way to execute a move-exception is as the first instruction 2698 * of an exception handler. 2699 * 2700 * Returns "true" if all is well, "false" if the target instruction is 2701 * move-exception. 2702 */ 2703 static bool checkMoveException(const Method* meth, int insnIdx, 2704 const char* logNote) 2705 { 2706 assert(insnIdx >= 0 && insnIdx < (int)dvmGetMethodInsnsSize(meth)); 2707 2708 if ((meth->insns[insnIdx] & 0xff) == OP_MOVE_EXCEPTION) { 2709 LOG_VFY("VFY: invalid use of move-exception\n"); 2710 return false; 2711 } 2712 return true; 2713 } 2714 2715 /* 2716 * For the "move-exception" instruction at "insnIdx", which must be at an 2717 * exception handler address, determine the first common superclass of 2718 * all exceptions that can land here. (For javac output, we're probably 2719 * looking at multiple spans of bytecode covered by one "try" that lands 2720 * at an exception-specific "catch", but in general the handler could be 2721 * shared for multiple exceptions.) 2722 * 2723 * Returns NULL if no matching exception handler can be found, or if the 2724 * exception is not a subclass of Throwable. 2725 */ 2726 static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx, 2727 VerifyError* pFailure) 2728 { 2729 VerifyError localFailure; 2730 const DexCode* pCode; 2731 DexFile* pDexFile; 2732 ClassObject* commonSuper = NULL; 2733 bool foundPossibleHandler = false; 2734 u4 handlersSize; 2735 u4 offset; 2736 u4 i; 2737 2738 pDexFile = meth->clazz->pDvmDex->pDexFile; 2739 pCode = dvmGetMethodCode(meth); 2740 2741 if (pCode->triesSize != 0) { 2742 handlersSize = dexGetHandlersSize(pCode); 2743 offset = dexGetFirstHandlerOffset(pCode); 2744 } else { 2745 handlersSize = 0; 2746 offset = 0; 2747 } 2748 2749 for (i = 0; i < handlersSize; i++) { 2750 DexCatchIterator iterator; 2751 dexCatchIteratorInit(&iterator, pCode, offset); 2752 2753 for (;;) { 2754 const DexCatchHandler* handler = dexCatchIteratorNext(&iterator); 2755 2756 if (handler == NULL) { 2757 break; 2758 } 2759 2760 if (handler->address == (u4) insnIdx) { 2761 ClassObject* clazz; 2762 foundPossibleHandler = true; 2763 2764 if (handler->typeIdx == kDexNoIndex) 2765 clazz = gDvm.classJavaLangThrowable; 2766 else 2767 clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx, 2768 &localFailure); 2769 2770 if (clazz == NULL) { 2771 LOG_VFY("VFY: unable to resolve exception class %u (%s)\n", 2772 handler->typeIdx, 2773 dexStringByTypeIdx(pDexFile, handler->typeIdx)); 2774 /* TODO: do we want to keep going? If we don't fail 2775 * this we run the risk of having a non-Throwable 2776 * introduced at runtime. However, that won't pass 2777 * an instanceof test, so is essentially harmless. */ 2778 } else { 2779 if (commonSuper == NULL) 2780 commonSuper = clazz; 2781 else 2782 commonSuper = findCommonSuperclass(clazz, commonSuper); 2783 } 2784 } 2785 } 2786 2787 offset = dexCatchIteratorGetEndOffset(&iterator, pCode); 2788 } 2789 2790 if (commonSuper == NULL) { 2791 /* no catch blocks, or no catches with classes we can find */ 2792 LOG_VFY_METH(meth, 2793 "VFY: unable to find exception handler at addr 0x%x\n", insnIdx); 2794 *pFailure = VERIFY_ERROR_GENERIC; 2795 } else { 2796 // TODO: verify the class is an instance of Throwable? 2797 } 2798 2799 return commonSuper; 2800 } 2801 2802 /* 2803 * Initialize the RegisterTable. 2804 * 2805 * Every instruction address can have a different set of information about 2806 * what's in which register, but for verification purposes we only need to 2807 * store it at branch target addresses (because we merge into that). 2808 * 2809 * By zeroing out the storage we are effectively initializing the register 2810 * information to kRegTypeUnknown. 2811 */ 2812 static bool initRegisterTable(const Method* meth, const InsnFlags* insnFlags, 2813 RegisterTable* regTable, RegisterTrackingMode trackRegsFor) 2814 { 2815 const int insnsSize = dvmGetMethodInsnsSize(meth); 2816 int i; 2817 2818 regTable->insnRegCountPlus = meth->registersSize + kExtraRegs; 2819 regTable->addrRegs = (RegType**) calloc(insnsSize, sizeof(RegType*)); 2820 if (regTable->addrRegs == NULL) 2821 return false; 2822 2823 assert(insnsSize > 0); 2824 2825 /* 2826 * "All" means "every address that holds the start of an instruction". 2827 * "Branches" and "GcPoints" mean just those addresses. 2828 * 2829 * "GcPoints" fills about half the addresses, "Branches" about 15%. 2830 */ 2831 int interestingCount = 0; 2832 //int insnCount = 0; 2833 2834 for (i = 0; i < insnsSize; i++) { 2835 bool interesting; 2836 2837 switch (trackRegsFor) { 2838 case kTrackRegsAll: 2839 interesting = dvmInsnIsOpcode(insnFlags, i); 2840 break; 2841 case kTrackRegsGcPoints: 2842 interesting = dvmInsnIsGcPoint(insnFlags, i) || 2843 dvmInsnIsBranchTarget(insnFlags, i); 2844 break; 2845 case kTrackRegsBranches: 2846 interesting = dvmInsnIsBranchTarget(insnFlags, i); 2847 break; 2848 default: 2849 dvmAbort(); 2850 return false; 2851 } 2852 2853 if (interesting) 2854 interestingCount++; 2855 2856 /* count instructions, for display only */ 2857 //if (dvmInsnIsOpcode(insnFlags, i)) 2858 // insnCount++; 2859 } 2860 2861 regTable->regAlloc = (RegType*) 2862 calloc(regTable->insnRegCountPlus * interestingCount, sizeof(RegType)); 2863 if (regTable->regAlloc == NULL) 2864 return false; 2865 2866 RegType* regPtr = regTable->regAlloc; 2867 for (i = 0; i < insnsSize; i++) { 2868 bool interesting; 2869 2870 switch (trackRegsFor) { 2871 case kTrackRegsAll: 2872 interesting = dvmInsnIsOpcode(insnFlags, i); 2873 break; 2874 case kTrackRegsGcPoints: 2875 interesting = dvmInsnIsGcPoint(insnFlags, i) || 2876 dvmInsnIsBranchTarget(insnFlags, i); 2877 break; 2878 case kTrackRegsBranches: 2879 interesting = dvmInsnIsBranchTarget(insnFlags, i); 2880 break; 2881 default: 2882 dvmAbort(); 2883 return false; 2884 } 2885 2886 if (interesting) { 2887 regTable->addrRegs[i] = regPtr; 2888 regPtr += regTable->insnRegCountPlus; 2889 } 2890 } 2891 2892 //LOGD("Tracking registers for %d, total %d of %d(%d) (%d%%)\n", 2893 // TRACK_REGS_FOR, interestingCount, insnCount, insnsSize, 2894 // (interestingCount*100) / insnCount); 2895 2896 assert(regPtr - regTable->regAlloc == 2897 regTable->insnRegCountPlus * interestingCount); 2898 assert(regTable->addrRegs[0] != NULL); 2899 return true; 2900 } 2901 2902 2903 /* 2904 * Verify that the arguments in a filled-new-array instruction are valid. 2905 * 2906 * "resClass" is the class refered to by pDecInsn->vB. 2907 */ 2908 static void verifyFilledNewArrayRegs(const Method* meth, 2909 const RegType* insnRegs, const int insnRegCount, 2910 const DecodedInstruction* pDecInsn, ClassObject* resClass, bool isRange, 2911 VerifyError* pFailure) 2912 { 2913 u4 argCount = pDecInsn->vA; 2914 RegType expectedType; 2915 PrimitiveType elemType; 2916 unsigned int ui; 2917 2918 assert(dvmIsArrayClass(resClass)); 2919 elemType = resClass->elementClass->primitiveType; 2920 if (elemType == PRIM_NOT) { 2921 expectedType = regTypeFromClass(resClass->elementClass); 2922 } else { 2923 expectedType = primitiveTypeToRegType(elemType); 2924 } 2925 //LOGI("filled-new-array: %s -> %d\n", resClass->descriptor, expectedType); 2926 2927 /* 2928 * Verify each register. If "argCount" is bad, verifyRegisterType() 2929 * will run off the end of the list and fail. It's legal, if silly, 2930 * for argCount to be zero. 2931 */ 2932 for (ui = 0; ui < argCount; ui++) { 2933 u4 getReg; 2934 2935 if (isRange) 2936 getReg = pDecInsn->vC + ui; 2937 else 2938 getReg = pDecInsn->arg[ui]; 2939 2940 verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType, 2941 pFailure); 2942 if (!VERIFY_OK(*pFailure)) { 2943 LOG_VFY("VFY: filled-new-array arg %u(%u) not valid\n", ui, getReg); 2944 return; 2945 } 2946 } 2947 } 2948 2949 2950 /* 2951 * Replace an instruction with "throw-verification-error". This allows us to 2952 * defer error reporting until the code path is first used. 2953 * 2954 * This is expected to be called during "just in time" verification, not 2955 * from within dexopt. (Verification failures in dexopt will result in 2956 * postponement of verification to first use of the class.) 2957 * 2958 * The throw-verification-error instruction requires two code units. Some 2959 * of the replaced instructions require three; the third code unit will 2960 * receive a "nop". The instruction's length will be left unchanged 2961 * in "insnFlags". 2962 * 2963 * The verifier explicitly locks out breakpoint activity, so there should 2964 * be no clashes with the debugger. 2965 * 2966 * Returns "true" on success. 2967 */ 2968 static bool replaceFailingInstruction(const Method* meth, InsnFlags* insnFlags, 2969 int insnIdx, VerifyError failure) 2970 { 2971 VerifyErrorRefType refType; 2972 const u2* oldInsns = meth->insns + insnIdx; 2973 u2 oldInsn = *oldInsns; 2974 bool result = false; 2975 2976 if (gDvm.optimizing) 2977 LOGD("Weird: RFI during dexopt?"); 2978 2979 //LOGD(" was 0x%04x\n", oldInsn); 2980 u2* newInsns = (u2*) meth->insns + insnIdx; 2981 2982 /* 2983 * Generate the new instruction out of the old. 2984 * 2985 * First, make sure this is an instruction we're expecting to stomp on. 2986 */ 2987 switch (oldInsn & 0xff) { 2988 case OP_CONST_CLASS: // insn[1] == class ref, 2 bytes 2989 case OP_CHECK_CAST: 2990 case OP_INSTANCE_OF: 2991 case OP_NEW_INSTANCE: 2992 case OP_NEW_ARRAY: 2993 case OP_FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes 2994 case OP_FILLED_NEW_ARRAY_RANGE: 2995 refType = VERIFY_ERROR_REF_CLASS; 2996 break; 2997 2998 case OP_IGET: // insn[1] == field ref, 2 bytes 2999 case OP_IGET_BOOLEAN: 3000 case OP_IGET_BYTE: 3001 case OP_IGET_CHAR: 3002 case OP_IGET_SHORT: 3003 case OP_IGET_WIDE: 3004 case OP_IGET_OBJECT: 3005 case OP_IPUT: 3006 case OP_IPUT_BOOLEAN: 3007 case OP_IPUT_BYTE: 3008 case OP_IPUT_CHAR: 3009 case OP_IPUT_SHORT: 3010 case OP_IPUT_WIDE: 3011 case OP_IPUT_OBJECT: 3012 case OP_SGET: 3013 case OP_SGET_BOOLEAN: 3014 case OP_SGET_BYTE: 3015 case OP_SGET_CHAR: 3016 case OP_SGET_SHORT: 3017 case OP_SGET_WIDE: 3018 case OP_SGET_OBJECT: 3019 case OP_SPUT: 3020 case OP_SPUT_BOOLEAN: 3021 case OP_SPUT_BYTE: 3022 case OP_SPUT_CHAR: 3023 case OP_SPUT_SHORT: 3024 case OP_SPUT_WIDE: 3025 case OP_SPUT_OBJECT: 3026 refType = VERIFY_ERROR_REF_FIELD; 3027 break; 3028 3029 case OP_INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes 3030 case OP_INVOKE_VIRTUAL_RANGE: 3031 case OP_INVOKE_SUPER: 3032 case OP_INVOKE_SUPER_RANGE: 3033 case OP_INVOKE_DIRECT: 3034 case OP_INVOKE_DIRECT_RANGE: 3035 case OP_INVOKE_STATIC: 3036 case OP_INVOKE_STATIC_RANGE: 3037 case OP_INVOKE_INTERFACE: 3038 case OP_INVOKE_INTERFACE_RANGE: 3039 refType = VERIFY_ERROR_REF_METHOD; 3040 break; 3041 3042 default: 3043 /* could handle this in a generic way, but this is probably safer */ 3044 LOG_VFY("GLITCH: verifier asked to replace opcode 0x%02x\n", 3045 oldInsn & 0xff); 3046 goto bail; 3047 } 3048 3049 /* write a NOP over the third code unit, if necessary */ 3050 int width = dvmInsnGetWidth(insnFlags, insnIdx); 3051 switch (width) { 3052 case 2: 3053 /* nothing to do */ 3054 break; 3055 case 3: 3056 dvmDexChangeDex2(meth->clazz->pDvmDex, newInsns+2, OP_NOP); 3057 //newInsns[2] = OP_NOP; 3058 break; 3059 default: 3060 /* whoops */ 3061 LOGE("ERROR: stomped a %d-unit instruction with a verifier error\n", 3062 width); 3063 dvmAbort(); 3064 } 3065 3066 /* encode the opcode, with the failure code in the high byte */ 3067 u2 newVal = OP_THROW_VERIFICATION_ERROR | 3068 (failure << 8) | (refType << (8 + kVerifyErrorRefTypeShift)); 3069 //newInsns[0] = newVal; 3070 dvmDexChangeDex2(meth->clazz->pDvmDex, newInsns, newVal); 3071 3072 result = true; 3073 3074 bail: 3075 return result; 3076 } 3077 3078 3079 /* 3080 * =========================================================================== 3081 * Entry point and driver loop 3082 * =========================================================================== 3083 */ 3084 3085 /* 3086 * Entry point for the detailed code-flow analysis. 3087 */ 3088 bool dvmVerifyCodeFlow(VerifierData* vdata) 3089 { 3090 bool result = false; 3091 const Method* meth = vdata->method; 3092 const int insnsSize = vdata->insnsSize; 3093 const bool generateRegisterMap = gDvm.generateRegisterMaps; 3094 RegisterTable regTable; 3095 3096 memset(®Table, 0, sizeof(regTable)); 3097 3098 #ifndef NDEBUG 3099 checkMergeTab(); // only need to do this if table gets updated 3100 #endif 3101 3102 /* 3103 * We rely on these for verification of const-class, const-string, 3104 * and throw instructions. Make sure we have them. 3105 */ 3106 if (gDvm.classJavaLangClass == NULL) 3107 gDvm.classJavaLangClass = 3108 dvmFindSystemClassNoInit("Ljava/lang/Class;"); 3109 if (gDvm.classJavaLangString == NULL) 3110 gDvm.classJavaLangString = 3111 dvmFindSystemClassNoInit("Ljava/lang/String;"); 3112 if (gDvm.classJavaLangThrowable == NULL) { 3113 gDvm.classJavaLangThrowable = 3114 dvmFindSystemClassNoInit("Ljava/lang/Throwable;"); 3115 gDvm.offJavaLangThrowable_cause = 3116 dvmFindFieldOffset(gDvm.classJavaLangThrowable, 3117 "cause", "Ljava/lang/Throwable;"); 3118 } 3119 if (gDvm.classJavaLangObject == NULL) 3120 gDvm.classJavaLangObject = 3121 dvmFindSystemClassNoInit("Ljava/lang/Object;"); 3122 3123 if (meth->registersSize * insnsSize > 4*1024*1024) { 3124 LOG_VFY_METH(meth, 3125 "VFY: warning: method is huge (regs=%d insnsSize=%d)\n", 3126 meth->registersSize, insnsSize); 3127 /* might be bogus data, might be some huge generated method */ 3128 } 3129 3130 /* 3131 * Create register lists, and initialize them to "Unknown". If we're 3132 * also going to create the register map, we need to retain the 3133 * register lists for a larger set of addresses. 3134 */ 3135 if (!initRegisterTable(meth, vdata->insnFlags, ®Table, 3136 generateRegisterMap ? kTrackRegsGcPoints : kTrackRegsBranches)) 3137 goto bail; 3138 3139 vdata->addrRegs = NULL; /* don't set this until we need it */ 3140 3141 /* 3142 * Initialize the types of the registers that correspond to the 3143 * method arguments. We can determine this from the method signature. 3144 */ 3145 if (!setTypesFromSignature(meth, regTable.addrRegs[0], vdata->uninitMap)) 3146 goto bail; 3147 3148 /* 3149 * Run the verifier. 3150 */ 3151 if (!doCodeVerification(meth, vdata->insnFlags, ®Table, vdata->uninitMap)) 3152 goto bail; 3153 3154 /* 3155 * Generate a register map. 3156 */ 3157 if (generateRegisterMap) { 3158 vdata->addrRegs = regTable.addrRegs; 3159 3160 RegisterMap* pMap = dvmGenerateRegisterMapV(vdata); 3161 if (pMap != NULL) { 3162 /* 3163 * Tuck it into the Method struct. It will either get used 3164 * directly or, if we're in dexopt, will be packed up and 3165 * appended to the DEX file. 3166 */ 3167 dvmSetRegisterMap((Method*)meth, pMap); 3168 } 3169 } 3170 3171 /* 3172 * Success. 3173 */ 3174 result = true; 3175 3176 bail: 3177 free(regTable.addrRegs); 3178 free(regTable.regAlloc); 3179 return result; 3180 } 3181 3182 /* 3183 * Grind through the instructions. 3184 * 3185 * The basic strategy is as outlined in v3 4.11.1.2: set the "changed" bit 3186 * on the first instruction, process it (setting additional "changed" bits), 3187 * and repeat until there are no more. 3188 * 3189 * v3 4.11.1.1 3190 * - (N/A) operand stack is always the same size 3191 * - operand stack [registers] contain the correct types of values 3192 * - local variables [registers] contain the correct types of values 3193 * - methods are invoked with the appropriate arguments 3194 * - fields are assigned using values of appropriate types 3195 * - opcodes have the correct type values in operand registers 3196 * - there is never an uninitialized class instance in a local variable in 3197 * code protected by an exception handler (operand stack is okay, because 3198 * the operand stack is discarded when an exception is thrown) [can't 3199 * know what's a local var w/o the debug info -- should fall out of 3200 * register typing] 3201 * 3202 * v3 4.11.1.2 3203 * - execution cannot fall off the end of the code 3204 * 3205 * (We also do many of the items described in the "static checks" sections, 3206 * because it's easier to do them here.) 3207 * 3208 * We need an array of RegType values, one per register, for every 3209 * instruction. In theory this could become quite large -- up to several 3210 * megabytes for a monster function. For self-preservation we reject 3211 * anything that requires more than a certain amount of memory. (Typical 3212 * "large" should be on the order of 4K code units * 8 registers.) This 3213 * will likely have to be adjusted. 3214 * 3215 * 3216 * The spec forbids backward branches when there's an uninitialized reference 3217 * in a register. The idea is to prevent something like this: 3218 * loop: 3219 * move r1, r0 3220 * new-instance r0, MyClass 3221 * ... 3222 * if-eq rN, loop // once 3223 * initialize r0 3224 * 3225 * This leaves us with two different instances, both allocated by the 3226 * same instruction, but only one is initialized. The scheme outlined in 3227 * v3 4.11.1.4 wouldn't catch this, so they work around it by preventing 3228 * backward branches. We achieve identical results without restricting 3229 * code reordering by specifying that you can't execute the new-instance 3230 * instruction if a register contains an uninitialized instance created 3231 * by that same instrutcion. 3232 */ 3233 static bool doCodeVerification(const Method* meth, InsnFlags* insnFlags, 3234 RegisterTable* regTable, UninitInstanceMap* uninitMap) 3235 { 3236 const int insnsSize = dvmGetMethodInsnsSize(meth); 3237 RegType workRegs[meth->registersSize + kExtraRegs]; 3238 bool result = false; 3239 bool debugVerbose = false; 3240 int insnIdx, startGuess; 3241 3242 /* 3243 * Begin by marking the first instruction as "changed". 3244 */ 3245 dvmInsnSetChanged(insnFlags, 0, true); 3246 3247 if (doVerboseLogging(meth)) { 3248 IF_LOGI() { 3249 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 3250 LOGI("Now verifying: %s.%s %s (ins=%d regs=%d)\n", 3251 meth->clazz->descriptor, meth->name, desc, 3252 meth->insSize, meth->registersSize); 3253 LOGI(" ------ [0 4 8 12 16 20 24 28 32 36\n"); 3254 free(desc); 3255 } 3256 debugVerbose = true; 3257 gDebugVerbose = true; 3258 } else { 3259 gDebugVerbose = false; 3260 } 3261 3262 startGuess = 0; 3263 3264 /* 3265 * Continue until no instructions are marked "changed". 3266 */ 3267 while (true) { 3268 /* 3269 * Find the first marked one. Use "startGuess" as a way to find 3270 * one quickly. 3271 */ 3272 for (insnIdx = startGuess; insnIdx < insnsSize; insnIdx++) { 3273 if (dvmInsnIsChanged(insnFlags, insnIdx)) 3274 break; 3275 } 3276 3277 if (insnIdx == insnsSize) { 3278 if (startGuess != 0) { 3279 /* try again, starting from the top */ 3280 startGuess = 0; 3281 continue; 3282 } else { 3283 /* all flags are clear */ 3284 break; 3285 } 3286 } 3287 3288 /* 3289 * We carry the working set of registers from instruction to 3290 * instruction. If this address can be the target of a branch 3291 * (or throw) instruction, or if we're skipping around chasing 3292 * "changed" flags, we need to load the set of registers from 3293 * the table. 3294 * 3295 * Because we always prefer to continue on to the next instruction, 3296 * we should never have a situation where we have a stray 3297 * "changed" flag set on an instruction that isn't a branch target. 3298 */ 3299 if (dvmInsnIsBranchTarget(insnFlags, insnIdx)) { 3300 RegType* insnRegs = getRegisterLine(regTable, insnIdx); 3301 assert(insnRegs != NULL); 3302 copyRegisters(workRegs, insnRegs, meth->registersSize + kExtraRegs); 3303 3304 if (debugVerbose) { 3305 dumpRegTypes(meth, insnFlags, workRegs, insnIdx, NULL,uninitMap, 3306 SHOW_REG_DETAILS); 3307 } 3308 3309 } else { 3310 if (debugVerbose) { 3311 dumpRegTypes(meth, insnFlags, workRegs, insnIdx, NULL,uninitMap, 3312 SHOW_REG_DETAILS); 3313 } 3314 3315 #ifndef NDEBUG 3316 /* 3317 * Sanity check: retrieve the stored register line (assuming 3318 * a full table) and make sure it actually matches. 3319 */ 3320 RegType* insnRegs = getRegisterLine(regTable, insnIdx); 3321 if (insnRegs != NULL && 3322 compareRegisters(workRegs, insnRegs, 3323 meth->registersSize + kExtraRegs) != 0) 3324 { 3325 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 3326 LOG_VFY("HUH? workRegs diverged in %s.%s %s\n", 3327 meth->clazz->descriptor, meth->name, desc); 3328 free(desc); 3329 dumpRegTypes(meth, insnFlags, workRegs, 0, "work", 3330 uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS); 3331 dumpRegTypes(meth, insnFlags, insnRegs, 0, "insn", 3332 uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS); 3333 } 3334 #endif 3335 } 3336 3337 //LOGI("process %s.%s %s %d\n", 3338 // meth->clazz->descriptor, meth->name, meth->descriptor, insnIdx); 3339 if (!verifyInstruction(meth, insnFlags, regTable, workRegs, insnIdx, 3340 uninitMap, &startGuess)) 3341 { 3342 //LOGD("+++ %s bailing at %d\n", meth->name, insnIdx); 3343 goto bail; 3344 } 3345 3346 #if 0 3347 { 3348 static const int gcMask = kInstrCanBranch | kInstrCanSwitch | 3349 kInstrCanThrow | kInstrCanReturn; 3350 OpCode opCode = *(meth->insns + insnIdx) & 0xff; 3351 int flags = dexGetInstrFlags(gDvm.instrFlags, opCode); 3352 3353 /* 8, 16, 32, or 32*n -bit regs */ 3354 int regWidth = (meth->registersSize + 7) / 8; 3355 if (regWidth == 3) 3356 regWidth = 4; 3357 if (regWidth > 4) { 3358 regWidth = ((regWidth + 3) / 4) * 4; 3359 if (false) { 3360 LOGW("WOW: %d regs -> %d %s.%s\n", 3361 meth->registersSize, regWidth, 3362 meth->clazz->descriptor, meth->name); 3363 //x = true; 3364 } 3365 } 3366 3367 if ((flags & gcMask) != 0) { 3368 /* this is a potential GC point */ 3369 gDvm__gcInstr++; 3370 3371 if (insnsSize < 256) 3372 gDvm__gcData += 1; 3373 else 3374 gDvm__gcData += 2; 3375 gDvm__gcData += regWidth; 3376 } 3377 gDvm__gcSimpleData += regWidth; 3378 3379 gDvm__totalInstr++; 3380 } 3381 #endif 3382 3383 /* 3384 * Clear "changed" and mark as visited. 3385 */ 3386 dvmInsnSetVisited(insnFlags, insnIdx, true); 3387 dvmInsnSetChanged(insnFlags, insnIdx, false); 3388 } 3389 3390 if (DEAD_CODE_SCAN && !IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) { 3391 /* 3392 * Scan for dead code. There's nothing "evil" about dead code 3393 * (besides the wasted space), but it indicates a flaw somewhere 3394 * down the line, possibly in the verifier. 3395 * 3396 * If we've rewritten "always throw" instructions into the stream, 3397 * we are almost certainly going to have some dead code. 3398 */ 3399 int deadStart = -1; 3400 for (insnIdx = 0; insnIdx < insnsSize; 3401 insnIdx += dvmInsnGetWidth(insnFlags, insnIdx)) 3402 { 3403 /* 3404 * Switch-statement data doesn't get "visited" by scanner. It 3405 * may or may not be preceded by a padding NOP. 3406 */ 3407 int instr = meth->insns[insnIdx]; 3408 if (instr == kPackedSwitchSignature || 3409 instr == kSparseSwitchSignature || 3410 instr == kArrayDataSignature || 3411 (instr == OP_NOP && 3412 (meth->insns[insnIdx+1] == kPackedSwitchSignature || 3413 meth->insns[insnIdx+1] == kSparseSwitchSignature || 3414 meth->insns[insnIdx+1] == kArrayDataSignature))) 3415 { 3416 dvmInsnSetVisited(insnFlags, insnIdx, true); 3417 } 3418 3419 if (!dvmInsnIsVisited(insnFlags, insnIdx)) { 3420 if (deadStart < 0) 3421 deadStart = insnIdx; 3422 } else if (deadStart >= 0) { 3423 IF_LOGD() { 3424 char* desc = 3425 dexProtoCopyMethodDescriptor(&meth->prototype); 3426 LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s\n", 3427 deadStart, insnIdx-1, 3428 meth->clazz->descriptor, meth->name, desc); 3429 free(desc); 3430 } 3431 3432 deadStart = -1; 3433 } 3434 } 3435 if (deadStart >= 0) { 3436 IF_LOGD() { 3437 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype); 3438 LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s\n", 3439 deadStart, insnIdx-1, 3440 meth->clazz->descriptor, meth->name, desc); 3441 free(desc); 3442 } 3443 } 3444 } 3445 3446 result = true; 3447 3448 bail: 3449 return result; 3450 } 3451 3452 3453 /* 3454 * Perform verification for a single instruction. 3455 * 3456 * This requires fully decoding the instruction to determine the effect 3457 * it has on registers. 3458 * 3459 * Finds zero or more following instructions and sets the "changed" flag 3460 * if execution at that point needs to be (re-)evaluated. Register changes 3461 * are merged into "regTypes" at the target addresses. Does not set or 3462 * clear any other flags in "insnFlags". 3463 * 3464 * This may alter meth->insns if we need to replace an instruction with 3465 * throw-verification-error. 3466 */ 3467 static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags, 3468 RegisterTable* regTable, RegType* workRegs, int insnIdx, 3469 UninitInstanceMap* uninitMap, int* pStartGuess) 3470 { 3471 const int insnsSize = dvmGetMethodInsnsSize(meth); 3472 const u2* insns = meth->insns + insnIdx; 3473 bool result = false; 3474 3475 /* 3476 * Once we finish decoding the instruction, we need to figure out where 3477 * we can go from here. There are three possible ways to transfer 3478 * control to another statement: 3479 * 3480 * (1) Continue to the next instruction. Applies to all but 3481 * unconditional branches, method returns, and exception throws. 3482 * (2) Branch to one or more possible locations. Applies to branches 3483 * and switch statements. 3484 * (3) Exception handlers. Applies to any instruction that can 3485 * throw an exception that is handled by an encompassing "try" 3486 * block. 3487 * 3488 * We can also return, in which case there is no successor instruction 3489 * from this point. 3490 * 3491 * The behavior can be determined from the InstructionFlags. 3492 */ 3493 3494 const DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile; 3495 RegType entryRegs[meth->registersSize + kExtraRegs]; 3496 ClassObject* resClass; 3497 int branchTarget = 0; 3498 const int insnRegCount = meth->registersSize; 3499 RegType tmpType; 3500 DecodedInstruction decInsn; 3501 bool justSetResult = false; 3502 VerifyError failure = VERIFY_ERROR_NONE; 3503 3504 #ifndef NDEBUG 3505 memset(&decInsn, 0x81, sizeof(decInsn)); 3506 #endif 3507 dexDecodeInstruction(gDvm.instrFormat, insns, &decInsn); 3508 3509 int nextFlags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode); 3510 3511 /* 3512 * Make a copy of the previous register state. If the instruction 3513 * throws an exception, we merge *this* into the destination rather 3514 * than workRegs, because we don't want the result from the "successful" 3515 * code path (e.g. a check-cast that "improves" a type) to be visible 3516 * to the exception handler. 3517 */ 3518 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx)) 3519 { 3520 copyRegisters(entryRegs, workRegs, meth->registersSize + kExtraRegs); 3521 } else { 3522 #ifndef NDEBUG 3523 memset(entryRegs, 0xdd, 3524 (meth->registersSize + kExtraRegs) * sizeof(RegType)); 3525 #endif 3526 } 3527 3528 switch (decInsn.opCode) { 3529 case OP_NOP: 3530 /* 3531 * A "pure" NOP has no effect on anything. Data tables start with 3532 * a signature that looks like a NOP; if we see one of these in 3533 * the course of executing code then we have a problem. 3534 */ 3535 if (decInsn.vA != 0) { 3536 LOG_VFY("VFY: encountered data table in instruction stream\n"); 3537 failure = VERIFY_ERROR_GENERIC; 3538 } 3539 break; 3540 3541 case OP_MOVE: 3542 case OP_MOVE_FROM16: 3543 case OP_MOVE_16: 3544 copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB, 3545 kTypeCategory1nr, &failure); 3546 break; 3547 case OP_MOVE_WIDE: 3548 case OP_MOVE_WIDE_FROM16: 3549 case OP_MOVE_WIDE_16: 3550 copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &failure); 3551 break; 3552 case OP_MOVE_OBJECT: 3553 case OP_MOVE_OBJECT_FROM16: 3554 case OP_MOVE_OBJECT_16: 3555 copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB, 3556 kTypeCategoryRef, &failure); 3557 break; 3558 3559 /* 3560 * The move-result instructions copy data out of a "pseudo-register" 3561 * with the results from the last method invocation. In practice we 3562 * might want to hold the result in an actual CPU register, so the 3563 * Dalvik spec requires that these only appear immediately after an 3564 * invoke or filled-new-array. 3565 * 3566 * These calls invalidate the "result" register. (This is now 3567 * redundant with the reset done below, but it can make the debug info 3568 * easier to read in some cases.) 3569 */ 3570 case OP_MOVE_RESULT: 3571 copyResultRegister1(workRegs, insnRegCount, decInsn.vA, 3572 kTypeCategory1nr, &failure); 3573 break; 3574 case OP_MOVE_RESULT_WIDE: 3575 copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &failure); 3576 break; 3577 case OP_MOVE_RESULT_OBJECT: 3578 copyResultRegister1(workRegs, insnRegCount, decInsn.vA, 3579 kTypeCategoryRef, &failure); 3580 break; 3581 3582 case OP_MOVE_EXCEPTION: 3583 /* 3584 * This statement can only appear as the first instruction in an 3585 * exception handler (though not all exception handlers need to 3586 * have one of these). We verify that as part of extracting the 3587 * exception type from the catch block list. 3588 * 3589 * "resClass" will hold the closest common superclass of all 3590 * exceptions that can be handled here. 3591 */ 3592 resClass = getCaughtExceptionType(meth, insnIdx, &failure); 3593 if (resClass == NULL) { 3594 assert(!VERIFY_OK(failure)); 3595 } else { 3596 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3597 regTypeFromClass(resClass), &failure); 3598 } 3599 break; 3600 3601 case OP_RETURN_VOID: 3602 if (!checkConstructorReturn(meth, workRegs, insnRegCount)) { 3603 failure = VERIFY_ERROR_GENERIC; 3604 } else if (getMethodReturnType(meth) != kRegTypeUnknown) { 3605 LOG_VFY("VFY: return-void not expected\n"); 3606 failure = VERIFY_ERROR_GENERIC; 3607 } 3608 break; 3609 case OP_RETURN: 3610 if (!checkConstructorReturn(meth, workRegs, insnRegCount)) { 3611 failure = VERIFY_ERROR_GENERIC; 3612 } else { 3613 /* check the method signature */ 3614 RegType returnType = getMethodReturnType(meth); 3615 checkTypeCategory(returnType, kTypeCategory1nr, &failure); 3616 if (!VERIFY_OK(failure)) 3617 LOG_VFY("VFY: return-32 not expected\n"); 3618 3619 /* check the register contents */ 3620 returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA, 3621 &failure); 3622 checkTypeCategory(returnType, kTypeCategory1nr, &failure); 3623 if (!VERIFY_OK(failure)) 3624 LOG_VFY("VFY: return-32 on invalid register v%d\n", decInsn.vA); 3625 } 3626 break; 3627 case OP_RETURN_WIDE: 3628 if (!checkConstructorReturn(meth, workRegs, insnRegCount)) { 3629 failure = VERIFY_ERROR_GENERIC; 3630 } else { 3631 RegType returnType, returnTypeHi; 3632 3633 /* check the method signature */ 3634 returnType = getMethodReturnType(meth); 3635 checkTypeCategory(returnType, kTypeCategory2, &failure); 3636 if (!VERIFY_OK(failure)) 3637 LOG_VFY("VFY: return-wide not expected\n"); 3638 3639 /* check the register contents */ 3640 returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA, 3641 &failure); 3642 returnTypeHi = getRegisterType(workRegs, insnRegCount, 3643 decInsn.vA +1, &failure); 3644 if (VERIFY_OK(failure)) { 3645 checkTypeCategory(returnType, kTypeCategory2, &failure); 3646 checkWidePair(returnType, returnTypeHi, &failure); 3647 } 3648 if (!VERIFY_OK(failure)) { 3649 LOG_VFY("VFY: return-wide on invalid register pair v%d\n", 3650 decInsn.vA); 3651 } 3652 } 3653 break; 3654 case OP_RETURN_OBJECT: 3655 if (!checkConstructorReturn(meth, workRegs, insnRegCount)) { 3656 failure = VERIFY_ERROR_GENERIC; 3657 } else { 3658 RegType returnType = getMethodReturnType(meth); 3659 checkTypeCategory(returnType, kTypeCategoryRef, &failure); 3660 if (!VERIFY_OK(failure)) { 3661 LOG_VFY("VFY: return-object not expected\n"); 3662 break; 3663 } 3664 3665 /* returnType is the *expected* return type, not register value */ 3666 assert(returnType != kRegTypeZero); 3667 assert(!regTypeIsUninitReference(returnType)); 3668 3669 /* 3670 * Verify that the reference in vAA is an instance of the type 3671 * in "returnType". The Zero type is allowed here. If the 3672 * method is declared to return an interface, then any 3673 * initialized reference is acceptable. 3674 * 3675 * Note getClassFromRegister fails if the register holds an 3676 * uninitialized reference, so we do not allow them to be 3677 * returned. 3678 */ 3679 ClassObject* declClass; 3680 3681 declClass = regTypeInitializedReferenceToClass(returnType); 3682 resClass = getClassFromRegister(workRegs, insnRegCount, 3683 decInsn.vA, &failure); 3684 if (!VERIFY_OK(failure)) 3685 break; 3686 if (resClass != NULL) { 3687 if (!dvmIsInterfaceClass(declClass) && 3688 !dvmInstanceof(resClass, declClass)) 3689 { 3690 LOG_VFY("VFY: returning %s (cl=%p), declared %s (cl=%p)\n", 3691 resClass->descriptor, resClass->classLoader, 3692 declClass->descriptor, declClass->classLoader); 3693 failure = VERIFY_ERROR_GENERIC; 3694 break; 3695 } 3696 } 3697 } 3698 break; 3699 3700 case OP_CONST_4: 3701 case OP_CONST_16: 3702 case OP_CONST: 3703 /* could be boolean, int, float, or a null reference */ 3704 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3705 dvmDetermineCat1Const((s4)decInsn.vB), &failure); 3706 break; 3707 case OP_CONST_HIGH16: 3708 /* could be boolean, int, float, or a null reference */ 3709 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3710 dvmDetermineCat1Const((s4) decInsn.vB << 16), &failure); 3711 break; 3712 case OP_CONST_WIDE_16: 3713 case OP_CONST_WIDE_32: 3714 case OP_CONST_WIDE: 3715 case OP_CONST_WIDE_HIGH16: 3716 /* could be long or double; default to long and allow conversion */ 3717 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3718 kRegTypeLongLo, &failure); 3719 break; 3720 case OP_CONST_STRING: 3721 case OP_CONST_STRING_JUMBO: 3722 assert(gDvm.classJavaLangString != NULL); 3723 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3724 regTypeFromClass(gDvm.classJavaLangString), &failure); 3725 break; 3726 case OP_CONST_CLASS: 3727 assert(gDvm.classJavaLangClass != NULL); 3728 /* make sure we can resolve the class; access check is important */ 3729 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 3730 if (resClass == NULL) { 3731 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 3732 dvmLogUnableToResolveClass(badClassDesc, meth); 3733 LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s\n", 3734 decInsn.vB, badClassDesc, meth->clazz->descriptor); 3735 assert(failure != VERIFY_ERROR_GENERIC); 3736 } else { 3737 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3738 regTypeFromClass(gDvm.classJavaLangClass), &failure); 3739 } 3740 break; 3741 3742 case OP_MONITOR_ENTER: 3743 case OP_MONITOR_EXIT: 3744 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure); 3745 if (VERIFY_OK(failure)) { 3746 if (!regTypeIsReference(tmpType)) { 3747 LOG_VFY("VFY: monitor op on non-object\n"); 3748 failure = VERIFY_ERROR_GENERIC; 3749 } 3750 } 3751 break; 3752 3753 case OP_CHECK_CAST: 3754 /* 3755 * If this instruction succeeds, we will promote register vA to 3756 * the type in vB. (This could be a demotion -- not expected, so 3757 * we don't try to address it.) 3758 * 3759 * If it fails, an exception is thrown, which we deal with later 3760 * by ignoring the update to decInsn.vA when branching to a handler. 3761 */ 3762 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 3763 if (resClass == NULL) { 3764 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 3765 dvmLogUnableToResolveClass(badClassDesc, meth); 3766 LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s\n", 3767 decInsn.vB, badClassDesc, meth->clazz->descriptor); 3768 assert(failure != VERIFY_ERROR_GENERIC); 3769 } else { 3770 RegType origType; 3771 3772 origType = getRegisterType(workRegs, insnRegCount, decInsn.vA, 3773 &failure); 3774 if (!VERIFY_OK(failure)) 3775 break; 3776 if (!regTypeIsReference(origType)) { 3777 LOG_VFY("VFY: check-cast on non-reference in v%u\n",decInsn.vA); 3778 failure = VERIFY_ERROR_GENERIC; 3779 break; 3780 } 3781 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3782 regTypeFromClass(resClass), &failure); 3783 } 3784 break; 3785 case OP_INSTANCE_OF: 3786 /* make sure we're checking a reference type */ 3787 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure); 3788 if (!VERIFY_OK(failure)) 3789 break; 3790 if (!regTypeIsReference(tmpType)) { 3791 LOG_VFY("VFY: vB not a reference (%d)\n", tmpType); 3792 failure = VERIFY_ERROR_GENERIC; 3793 break; 3794 } 3795 3796 /* make sure we can resolve the class; access check is important */ 3797 resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure); 3798 if (resClass == NULL) { 3799 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC); 3800 dvmLogUnableToResolveClass(badClassDesc, meth); 3801 LOG_VFY("VFY: unable to resolve instanceof %d (%s) in %s\n", 3802 decInsn.vC, badClassDesc, meth->clazz->descriptor); 3803 assert(failure != VERIFY_ERROR_GENERIC); 3804 } else { 3805 /* result is boolean */ 3806 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3807 kRegTypeBoolean, &failure); 3808 } 3809 break; 3810 3811 case OP_ARRAY_LENGTH: 3812 resClass = getClassFromRegister(workRegs, insnRegCount, 3813 decInsn.vB, &failure); 3814 if (!VERIFY_OK(failure)) 3815 break; 3816 if (resClass != NULL && !dvmIsArrayClass(resClass)) { 3817 LOG_VFY("VFY: array-length on non-array\n"); 3818 failure = VERIFY_ERROR_GENERIC; 3819 break; 3820 } 3821 setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeInteger, 3822 &failure); 3823 break; 3824 3825 case OP_NEW_INSTANCE: 3826 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 3827 if (resClass == NULL) { 3828 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 3829 dvmLogUnableToResolveClass(badClassDesc, meth); 3830 LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s\n", 3831 decInsn.vB, badClassDesc, meth->clazz->descriptor); 3832 assert(failure != VERIFY_ERROR_GENERIC); 3833 } else { 3834 RegType uninitType; 3835 3836 /* can't create an instance of an interface or abstract class */ 3837 if (dvmIsAbstractClass(resClass) || dvmIsInterfaceClass(resClass)) { 3838 LOG_VFY("VFY: new-instance on interface or abstract class %s\n", 3839 resClass->descriptor); 3840 failure = VERIFY_ERROR_INSTANTIATION; 3841 break; 3842 } 3843 3844 /* add resolved class to uninit map if not already there */ 3845 int uidx = dvmSetUninitInstance(uninitMap, insnIdx, resClass); 3846 assert(uidx >= 0); 3847 uninitType = regTypeFromUninitIndex(uidx); 3848 3849 /* 3850 * Any registers holding previous allocations from this address 3851 * that have not yet been initialized must be marked invalid. 3852 */ 3853 markUninitRefsAsInvalid(workRegs, insnRegCount, uninitMap, 3854 uninitType); 3855 3856 /* add the new uninitialized reference to the register ste */ 3857 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3858 uninitType, &failure); 3859 } 3860 break; 3861 case OP_NEW_ARRAY: 3862 resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure); 3863 if (resClass == NULL) { 3864 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC); 3865 dvmLogUnableToResolveClass(badClassDesc, meth); 3866 LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s\n", 3867 decInsn.vC, badClassDesc, meth->clazz->descriptor); 3868 assert(failure != VERIFY_ERROR_GENERIC); 3869 } else if (!dvmIsArrayClass(resClass)) { 3870 LOG_VFY("VFY: new-array on non-array class\n"); 3871 failure = VERIFY_ERROR_GENERIC; 3872 } else { 3873 /* make sure "size" register is valid type */ 3874 verifyRegisterType(workRegs, insnRegCount, decInsn.vB, 3875 kRegTypeInteger, &failure); 3876 /* set register type to array class */ 3877 setRegisterType(workRegs, insnRegCount, decInsn.vA, 3878 regTypeFromClass(resClass), &failure); 3879 } 3880 break; 3881 case OP_FILLED_NEW_ARRAY: 3882 case OP_FILLED_NEW_ARRAY_RANGE: 3883 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure); 3884 if (resClass == NULL) { 3885 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB); 3886 dvmLogUnableToResolveClass(badClassDesc, meth); 3887 LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s\n", 3888 decInsn.vB, badClassDesc, meth->clazz->descriptor); 3889 assert(failure != VERIFY_ERROR_GENERIC); 3890 } else if (!dvmIsArrayClass(resClass)) { 3891 LOG_VFY("VFY: filled-new-array on non-array class\n"); 3892 failure = VERIFY_ERROR_GENERIC; 3893 } else { 3894 bool isRange = (decInsn.opCode == OP_FILLED_NEW_ARRAY_RANGE); 3895 3896 /* check the arguments to the instruction */ 3897 verifyFilledNewArrayRegs(meth, workRegs, insnRegCount, &decInsn, 3898 resClass, isRange, &failure); 3899 /* filled-array result goes into "result" register */ 3900 setResultRegisterType(workRegs, insnRegCount, 3901 regTypeFromClass(resClass), &failure); 3902 justSetResult = true; 3903 } 3904 break; 3905 3906 case OP_CMPL_FLOAT: 3907 case OP_CMPG_FLOAT: 3908 verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeFloat, 3909 &failure); 3910 verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeFloat, 3911 &failure); 3912 setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean, 3913 &failure); 3914 break; 3915 case OP_CMPL_DOUBLE: 3916 case OP_CMPG_DOUBLE: 3917 verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeDoubleLo, 3918 &failure); 3919 verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeDoubleLo, 3920 &failure); 3921 setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean, 3922 &failure); 3923 break; 3924 case OP_CMP_LONG: 3925 verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeLongLo, 3926 &failure); 3927 verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeLongLo, 3928 &failure); 3929 setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean, 3930 &failure); 3931 break; 3932 3933 case OP_THROW: 3934 resClass = getClassFromRegister(workRegs, insnRegCount, 3935 decInsn.vA, &failure); 3936 if (VERIFY_OK(failure) && resClass != NULL) { 3937 if (!dvmInstanceof(resClass, gDvm.classJavaLangThrowable)) { 3938 LOG_VFY("VFY: thrown class %s not instanceof Throwable\n", 3939 resClass->descriptor); 3940 failure = VERIFY_ERROR_GENERIC; 3941 } 3942 } 3943 break; 3944 3945 case OP_GOTO: 3946 case OP_GOTO_16: 3947 case OP_GOTO_32: 3948 /* no effect on or use of registers */ 3949 break; 3950 3951 case OP_PACKED_SWITCH: 3952 case OP_SPARSE_SWITCH: 3953 /* verify that vAA is an integer, or can be converted to one */ 3954 verifyRegisterType(workRegs, insnRegCount, decInsn.vA, 3955 kRegTypeInteger, &failure); 3956 break; 3957 3958 case OP_FILL_ARRAY_DATA: 3959 { 3960 RegType valueType; 3961 const u2 *arrayData; 3962 u2 elemWidth; 3963 3964 /* Similar to the verification done for APUT */ 3965 resClass = getClassFromRegister(workRegs, insnRegCount, 3966 decInsn.vA, &failure); 3967 if (!VERIFY_OK(failure)) 3968 break; 3969 3970 /* resClass can be null if the reg type is Zero */ 3971 if (resClass == NULL) 3972 break; 3973 3974 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 3975 resClass->elementClass->primitiveType == PRIM_NOT || 3976 resClass->elementClass->primitiveType == PRIM_VOID) 3977 { 3978 LOG_VFY("VFY: invalid fill-array-data on %s\n", 3979 resClass->descriptor); 3980 failure = VERIFY_ERROR_GENERIC; 3981 break; 3982 } 3983 3984 valueType = primitiveTypeToRegType( 3985 resClass->elementClass->primitiveType); 3986 assert(valueType != kRegTypeUnknown); 3987 3988 /* 3989 * Now verify if the element width in the table matches the element 3990 * width declared in the array 3991 */ 3992 arrayData = insns + (insns[1] | (((s4)insns[2]) << 16)); 3993 if (arrayData[0] != kArrayDataSignature) { 3994 LOG_VFY("VFY: invalid magic for array-data\n"); 3995 failure = VERIFY_ERROR_GENERIC; 3996 break; 3997 } 3998 3999 switch (resClass->elementClass->primitiveType) { 4000 case PRIM_BOOLEAN: 4001 case PRIM_BYTE: 4002 elemWidth = 1; 4003 break; 4004 case PRIM_CHAR: 4005 case PRIM_SHORT: 4006 elemWidth = 2; 4007 break; 4008 case PRIM_FLOAT: 4009 case PRIM_INT: 4010 elemWidth = 4; 4011 break; 4012 case PRIM_DOUBLE: 4013 case PRIM_LONG: 4014 elemWidth = 8; 4015 break; 4016 default: 4017 elemWidth = 0; 4018 break; 4019 } 4020 4021 /* 4022 * Since we don't compress the data in Dex, expect to see equal 4023 * width of data stored in the table and expected from the array 4024 * class. 4025 */ 4026 if (arrayData[1] != elemWidth) { 4027 LOG_VFY("VFY: array-data size mismatch (%d vs %d)\n", 4028 arrayData[1], elemWidth); 4029 failure = VERIFY_ERROR_GENERIC; 4030 } 4031 } 4032 break; 4033 4034 case OP_IF_EQ: 4035 case OP_IF_NE: 4036 { 4037 RegType type1, type2; 4038 4039 type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA, 4040 &failure); 4041 type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB, 4042 &failure); 4043 if (!VERIFY_OK(failure)) 4044 break; 4045 4046 /* both references? */ 4047 if (regTypeIsReference(type1) && regTypeIsReference(type2)) 4048 break; 4049 4050 /* both category-1nr? */ 4051 checkTypeCategory(type1, kTypeCategory1nr, &failure); 4052 checkTypeCategory(type2, kTypeCategory1nr, &failure); 4053 if (!VERIFY_OK(failure)) { 4054 LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1\n"); 4055 break; 4056 } 4057 } 4058 break; 4059 case OP_IF_LT: 4060 case OP_IF_GE: 4061 case OP_IF_GT: 4062 case OP_IF_LE: 4063 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure); 4064 if (!VERIFY_OK(failure)) 4065 break; 4066 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4067 if (!VERIFY_OK(failure)) { 4068 LOG_VFY("VFY: args to 'if' must be cat-1nr\n"); 4069 break; 4070 } 4071 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure); 4072 if (!VERIFY_OK(failure)) 4073 break; 4074 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4075 if (!VERIFY_OK(failure)) { 4076 LOG_VFY("VFY: args to 'if' must be cat-1nr\n"); 4077 break; 4078 } 4079 break; 4080 case OP_IF_EQZ: 4081 case OP_IF_NEZ: 4082 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure); 4083 if (!VERIFY_OK(failure)) 4084 break; 4085 if (regTypeIsReference(tmpType)) 4086 break; 4087 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4088 if (!VERIFY_OK(failure)) 4089 LOG_VFY("VFY: expected cat-1 arg to if\n"); 4090 break; 4091 case OP_IF_LTZ: 4092 case OP_IF_GEZ: 4093 case OP_IF_GTZ: 4094 case OP_IF_LEZ: 4095 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure); 4096 if (!VERIFY_OK(failure)) 4097 break; 4098 checkTypeCategory(tmpType, kTypeCategory1nr, &failure); 4099 if (!VERIFY_OK(failure)) 4100 LOG_VFY("VFY: expected cat-1 arg to if\n"); 4101 break; 4102 4103 case OP_AGET: 4104 tmpType = kRegTypeInteger; 4105 goto aget_1nr_common; 4106 case OP_AGET_BOOLEAN: 4107 tmpType = kRegTypeBoolean; 4108 goto aget_1nr_common; 4109 case OP_AGET_BYTE: 4110 tmpType = kRegTypeByte; 4111 goto aget_1nr_common; 4112 case OP_AGET_CHAR: 4113 tmpType = kRegTypeChar; 4114 goto aget_1nr_common; 4115 case OP_AGET_SHORT: 4116 tmpType = kRegTypeShort; 4117 goto aget_1nr_common; 4118 aget_1nr_common: 4119 { 4120 RegType srcType, indexType; 4121 4122 indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC, 4123 &failure); 4124 checkArrayIndexType(meth, indexType, &failure); 4125 if (!VERIFY_OK(failure)) 4126 break; 4127 4128 resClass = getClassFromRegister(workRegs, insnRegCount, 4129 decInsn.vB, &failure); 4130 if (!VERIFY_OK(failure)) 4131 break; 4132 if (resClass != NULL) { 4133 /* verify the class */ 4134 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4135 resClass->elementClass->primitiveType == PRIM_NOT) 4136 { 4137 LOG_VFY("VFY: invalid aget-1nr target %s\n", 4138 resClass->descriptor); 4139 failure = VERIFY_ERROR_GENERIC; 4140 break; 4141 } 4142 4143 /* make sure array type matches instruction */ 4144 srcType = primitiveTypeToRegType( 4145 resClass->elementClass->primitiveType); 4146 4147 if (!checkFieldArrayStore1nr(tmpType, srcType)) { 4148 LOG_VFY("VFY: invalid aget-1nr, array type=%d with" 4149 " inst type=%d (on %s)\n", 4150 srcType, tmpType, resClass->descriptor); 4151 failure = VERIFY_ERROR_GENERIC; 4152 break; 4153 } 4154 4155 } 4156 setRegisterType(workRegs, insnRegCount, decInsn.vA, 4157 tmpType, &failure); 4158 } 4159 break; 4160 4161 case OP_AGET_WIDE: 4162 { 4163 RegType dstType, indexType; 4164 4165 indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC, 4166 &failure); 4167 checkArrayIndexType(meth, indexType, &failure); 4168 if (!VERIFY_OK(failure)) 4169 break; 4170 4171 resClass = getClassFromRegister(workRegs, insnRegCount, 4172 decInsn.vB, &failure); 4173 if (!VERIFY_OK(failure)) 4174 break; 4175 if (resClass != NULL) { 4176 /* verify the class */ 4177 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4178 resClass->elementClass->primitiveType == PRIM_NOT) 4179 { 4180 LOG_VFY("VFY: invalid aget-wide target %s\n", 4181 resClass->descriptor); 4182 failure = VERIFY_ERROR_GENERIC; 4183 break; 4184 } 4185 4186 /* try to refine "dstType" */ 4187 switch (resClass->elementClass->primitiveType) { 4188 case PRIM_LONG: 4189 dstType = kRegTypeLongLo; 4190 break; 4191 case PRIM_DOUBLE: 4192 dstType = kRegTypeDoubleLo; 4193 break; 4194 default: 4195 LOG_VFY("VFY: invalid aget-wide on %s\n", 4196 resClass->descriptor); 4197 dstType = kRegTypeUnknown; 4198 failure = VERIFY_ERROR_GENERIC; 4199 break; 4200 } 4201 } else { 4202 /* 4203 * Null array ref; this code path will fail at runtime. We 4204 * know this is either long or double, and we don't really 4205 * discriminate between those during verification, so we 4206 * call it a long. 4207 */ 4208 dstType = kRegTypeLongLo; 4209 } 4210 setRegisterType(workRegs, insnRegCount, decInsn.vA, 4211 dstType, &failure); 4212 } 4213 break; 4214 4215 case OP_AGET_OBJECT: 4216 { 4217 RegType dstType, indexType; 4218 4219 indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC, 4220 &failure); 4221 checkArrayIndexType(meth, indexType, &failure); 4222 if (!VERIFY_OK(failure)) 4223 break; 4224 4225 /* get the class of the array we're pulling an object from */ 4226 resClass = getClassFromRegister(workRegs, insnRegCount, 4227 decInsn.vB, &failure); 4228 if (!VERIFY_OK(failure)) 4229 break; 4230 if (resClass != NULL) { 4231 ClassObject* elementClass; 4232 4233 assert(resClass != NULL); 4234 if (!dvmIsArrayClass(resClass)) { 4235 LOG_VFY("VFY: aget-object on non-array class\n"); 4236 failure = VERIFY_ERROR_GENERIC; 4237 break; 4238 } 4239 assert(resClass->elementClass != NULL); 4240 4241 /* 4242 * Find the element class. resClass->elementClass indicates 4243 * the basic type, which won't be what we want for a 4244 * multi-dimensional array. 4245 */ 4246 if (resClass->descriptor[1] == '[') { 4247 assert(resClass->arrayDim > 1); 4248 elementClass = dvmFindArrayClass(&resClass->descriptor[1], 4249 resClass->classLoader); 4250 } else if (resClass->descriptor[1] == 'L') { 4251 assert(resClass->arrayDim == 1); 4252 elementClass = resClass->elementClass; 4253 } else { 4254 LOG_VFY("VFY: aget-object on non-ref array class (%s)\n", 4255 resClass->descriptor); 4256 failure = VERIFY_ERROR_GENERIC; 4257 break; 4258 } 4259 4260 dstType = regTypeFromClass(elementClass); 4261 } else { 4262 /* 4263 * The array reference is NULL, so the current code path will 4264 * throw an exception. For proper merging with later code 4265 * paths, and correct handling of "if-eqz" tests on the 4266 * result of the array get, we want to treat this as a null 4267 * reference. 4268 */ 4269 dstType = kRegTypeZero; 4270 } 4271 setRegisterType(workRegs, insnRegCount, decInsn.vA, 4272 dstType, &failure); 4273 } 4274 break; 4275 case OP_APUT: 4276 tmpType = kRegTypeInteger; 4277 goto aput_1nr_common; 4278 case OP_APUT_BOOLEAN: 4279 tmpType = kRegTypeBoolean; 4280 goto aput_1nr_common; 4281 case OP_APUT_BYTE: 4282 tmpType = kRegTypeByte; 4283 goto aput_1nr_common; 4284 case OP_APUT_CHAR: 4285 tmpType = kRegTypeChar; 4286 goto aput_1nr_common; 4287 case OP_APUT_SHORT: 4288 tmpType = kRegTypeShort; 4289 goto aput_1nr_common; 4290 aput_1nr_common: 4291 { 4292 RegType srcType, dstType, indexType; 4293 4294 indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC, 4295 &failure); 4296 checkArrayIndexType(meth, indexType, &failure); 4297 if (!VERIFY_OK(failure)) 4298 break; 4299 4300 /* make sure the source register has the correct type */ 4301 srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA, 4302 &failure); 4303 if (!canConvertTo1nr(srcType, tmpType)) { 4304 LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)\n", 4305 srcType, tmpType); 4306 failure = VERIFY_ERROR_GENERIC; 4307 break; 4308 } 4309 4310 resClass = getClassFromRegister(workRegs, insnRegCount, 4311 decInsn.vB, &failure); 4312 if (!VERIFY_OK(failure)) 4313 break; 4314 4315 /* resClass can be null if the reg type is Zero */ 4316 if (resClass == NULL) 4317 break; 4318 4319 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4320 resClass->elementClass->primitiveType == PRIM_NOT) 4321 { 4322 LOG_VFY("VFY: invalid aput-1nr on %s\n", resClass->descriptor); 4323 failure = VERIFY_ERROR_GENERIC; 4324 break; 4325 } 4326 4327 /* verify that instruction matches array */ 4328 dstType = primitiveTypeToRegType( 4329 resClass->elementClass->primitiveType); 4330 assert(dstType != kRegTypeUnknown); 4331 4332 if (!checkFieldArrayStore1nr(tmpType, dstType)) { 4333 LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)\n", 4334 resClass->descriptor, tmpType, dstType); 4335 failure = VERIFY_ERROR_GENERIC; 4336 break; 4337 } 4338 } 4339 break; 4340 case OP_APUT_WIDE: 4341 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC, 4342 &failure); 4343 checkArrayIndexType(meth, tmpType, &failure); 4344 if (!VERIFY_OK(failure)) 4345 break; 4346 4347 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure); 4348 if (VERIFY_OK(failure)) { 4349 RegType typeHi = 4350 getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure); 4351 checkTypeCategory(tmpType, kTypeCategory2, &failure); 4352 checkWidePair(tmpType, typeHi, &failure); 4353 } 4354 if (!VERIFY_OK(failure)) 4355 break; 4356 4357 resClass = getClassFromRegister(workRegs, insnRegCount, 4358 decInsn.vB, &failure); 4359 if (!VERIFY_OK(failure)) 4360 break; 4361 if (resClass != NULL) { 4362 /* verify the class and try to refine "dstType" */ 4363 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 || 4364 resClass->elementClass->primitiveType == PRIM_NOT) 4365 { 4366 LOG_VFY("VFY: invalid aput-wide on %s\n", 4367 resClass->descriptor); 4368 failure = VERIFY_ERROR_GENERIC; 4369 break; 4370 } 4371 4372 switch (resClass->elementClass->primitiveType) { 4373 case PRIM_LONG: 4374 case PRIM_DOUBLE: 4375 /* these are okay */ 4376 break; 4377 default: 4378 LOG_VFY("VFY: invalid aput-wide on %s\n", 4379 resClass->descriptor); 4380 failure = VERIFY_ERROR_GENERIC; 4381 break; 4382 } 4383 } 4384 break; 4385 case OP_APUT_OBJECT: 4386 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC, 4387 &failure); 4388 checkArrayIndexType(meth, tmpType, &failure); 4389 if (!VERIFY_OK(failure)) 4390 break; 4391 4392 /* get the ref we're storing; Zero is okay, Uninit is not */ 4393 resClass = getClassFromRegister(workRegs, insnRegCount, 4394 decInsn.vA, &failure); 4395 if (!VERIFY_OK(failure)) 4396 break; 4397 if (resClass != NULL) { 4398 ClassObject* arrayClass; 4399 ClassObject* elementClass; 4400 4401 /* 4402 * Get the array class. If the array ref is null, we won't 4403 * have type information (and we'll crash at runtime with a 4404 * null pointer exception). 4405 */ 4406 arrayClass = getClassFromRegister(workRegs, insnRegCount, 4407 decInsn.vB, &failure); 4408 4409 if (arrayClass != NULL) { 4410 /* see if the array holds a compatible type */ 4411 if (!dvmIsArrayClass(arrayClass)) { 4412 LOG_VFY("VFY: invalid aput-object on %s\n", 4413 arrayClass->descriptor); 4414 failure = VERIFY_ERROR_GENERIC; 4415 break; 4416 } 4417 4418 /* 4419 * Find the element class. resClass->elementClass indicates 4420 * the basic type, which won't be what we want for a 4421 * multi-dimensional array. 4422 * 4423 * All we want to check here is that the element type is a 4424 * reference class. We *don't* check instanceof here, because 4425 * you can still put a String into a String[] after the latter 4426 * has been cast to an Object[]. 4427 */ 4428 if (arrayClass->descriptor[1] == '[') { 4429 assert(arrayClass->arrayDim > 1); 4430 elementClass = dvmFindArrayClass(&arrayClass->descriptor[1], 4431 arrayClass->classLoader); 4432 } else { 4433 assert(arrayClass->arrayDim == 1); 4434 elementClass = arrayClass->elementClass; 4435 } 4436 if (elementClass->primitiveType != PRIM_NOT) { 4437 LOG_VFY("VFY: invalid aput-object of %s into %s\n", 4438 resClass->descriptor, arrayClass->descriptor); 4439 failure = VERIFY_ERROR_GENERIC; 4440 break; 4441 } 4442 } 4443 } 4444 break; 4445 4446 case OP_IGET: 4447 case OP_IGET_VOLATILE: 4448 tmpType = kRegTypeInteger; 4449 goto iget_1nr_common; 4450 case OP_IGET_BOOLEAN: 4451 tmpType = kRegTypeBoolean; 4452 goto iget_1nr_common; 4453 case OP_IGET_BYTE: 4454 tmpType = kRegTypeByte; 4455 goto iget_1nr_common; 4456 case OP_IGET_CHAR: 4457 tmpType = kRegTypeChar; 4458 goto iget_1nr_common; 4459 case OP_IGET_SHORT: 4460 tmpType = kRegTypeShort; 4461 goto iget_1nr_common; 4462 iget_1nr_common: 4463 { 4464 InstField* instField; 4465 RegType objType, fieldType; 4466 4467 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB, 4468 &failure); 4469 if (!VERIFY_OK(failure)) 4470 break; 4471 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4472 &failure); 4473 if (!VERIFY_OK(failure)) 4474 break; 4475 4476 /* make sure the field's type is compatible with expectation */ 4477 fieldType = primSigCharToRegType(instField->field.signature[0]); 4478 if (fieldType == kRegTypeUnknown || 4479 !checkFieldArrayStore1nr(tmpType, fieldType)) 4480 { 4481 LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)\n", 4482 instField->field.clazz->descriptor, 4483 instField->field.name, tmpType, fieldType); 4484 failure = VERIFY_ERROR_GENERIC; 4485 break; 4486 } 4487 4488 setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, 4489 &failure); 4490 } 4491 break; 4492 case OP_IGET_WIDE: 4493 case OP_IGET_WIDE_VOLATILE: 4494 { 4495 RegType dstType; 4496 InstField* instField; 4497 RegType objType; 4498 4499 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB, 4500 &failure); 4501 if (!VERIFY_OK(failure)) 4502 break; 4503 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4504 &failure); 4505 if (!VERIFY_OK(failure)) 4506 break; 4507 /* check the type, which should be prim */ 4508 switch (instField->field.signature[0]) { 4509 case 'D': 4510 dstType = kRegTypeDoubleLo; 4511 break; 4512 case 'J': 4513 dstType = kRegTypeLongLo; 4514 break; 4515 default: 4516 LOG_VFY("VFY: invalid iget-wide of %s.%s\n", 4517 instField->field.clazz->descriptor, 4518 instField->field.name); 4519 dstType = kRegTypeUnknown; 4520 failure = VERIFY_ERROR_GENERIC; 4521 break; 4522 } 4523 if (VERIFY_OK(failure)) { 4524 setRegisterType(workRegs, insnRegCount, decInsn.vA, 4525 dstType, &failure); 4526 } 4527 } 4528 break; 4529 case OP_IGET_OBJECT: 4530 case OP_IGET_OBJECT_VOLATILE: 4531 { 4532 ClassObject* fieldClass; 4533 InstField* instField; 4534 RegType objType; 4535 4536 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB, 4537 &failure); 4538 if (!VERIFY_OK(failure)) 4539 break; 4540 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4541 &failure); 4542 if (!VERIFY_OK(failure)) 4543 break; 4544 fieldClass = getFieldClass(meth, &instField->field); 4545 if (fieldClass == NULL) { 4546 /* class not found or primitive type */ 4547 LOG_VFY("VFY: unable to recover field class from '%s'\n", 4548 instField->field.signature); 4549 failure = VERIFY_ERROR_GENERIC; 4550 break; 4551 } 4552 if (VERIFY_OK(failure)) { 4553 assert(!dvmIsPrimitiveClass(fieldClass)); 4554 setRegisterType(workRegs, insnRegCount, decInsn.vA, 4555 regTypeFromClass(fieldClass), &failure); 4556 } 4557 } 4558 break; 4559 case OP_IPUT: 4560 case OP_IPUT_VOLATILE: 4561 tmpType = kRegTypeInteger; 4562 goto iput_1nr_common; 4563 case OP_IPUT_BOOLEAN: 4564 tmpType = kRegTypeBoolean; 4565 goto iput_1nr_common; 4566 case OP_IPUT_BYTE: 4567 tmpType = kRegTypeByte; 4568 goto iput_1nr_common; 4569 case OP_IPUT_CHAR: 4570 tmpType = kRegTypeChar; 4571 goto iput_1nr_common; 4572 case OP_IPUT_SHORT: 4573 tmpType = kRegTypeShort; 4574 goto iput_1nr_common; 4575 iput_1nr_common: 4576 { 4577 RegType srcType, fieldType, objType; 4578 InstField* instField; 4579 4580 srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA, 4581 &failure); 4582 4583 /* 4584 * javac generates synthetic functions that write byte values 4585 * into boolean fields. 4586 */ 4587 if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte) 4588 srcType = kRegTypeBoolean; 4589 4590 /* make sure the source register has the correct type */ 4591 if (!canConvertTo1nr(srcType, tmpType)) { 4592 LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n", 4593 srcType, tmpType); 4594 failure = VERIFY_ERROR_GENERIC; 4595 break; 4596 } 4597 4598 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB, 4599 &failure); 4600 if (!VERIFY_OK(failure)) 4601 break; 4602 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4603 &failure); 4604 if (!VERIFY_OK(failure)) 4605 break; 4606 checkFinalFieldAccess(meth, &instField->field, &failure); 4607 if (!VERIFY_OK(failure)) 4608 break; 4609 4610 /* get type of field we're storing into */ 4611 fieldType = primSigCharToRegType(instField->field.signature[0]); 4612 if (fieldType == kRegTypeUnknown || 4613 !checkFieldArrayStore1nr(tmpType, fieldType)) 4614 { 4615 LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)\n", 4616 instField->field.clazz->descriptor, 4617 instField->field.name, tmpType, fieldType); 4618 failure = VERIFY_ERROR_GENERIC; 4619 break; 4620 } 4621 } 4622 break; 4623 case OP_IPUT_WIDE: 4624 case OP_IPUT_WIDE_VOLATILE: 4625 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure); 4626 if (VERIFY_OK(failure)) { 4627 RegType typeHi = 4628 getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure); 4629 checkTypeCategory(tmpType, kTypeCategory2, &failure); 4630 checkWidePair(tmpType, typeHi, &failure); 4631 } 4632 if (VERIFY_OK(failure)) { 4633 InstField* instField; 4634 RegType objType; 4635 4636 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB, 4637 &failure); 4638 if (!VERIFY_OK(failure)) 4639 break; 4640 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4641 &failure); 4642 if (!VERIFY_OK(failure)) 4643 break; 4644 checkFinalFieldAccess(meth, &instField->field, &failure); 4645 if (!VERIFY_OK(failure)) 4646 break; 4647 4648 /* check the type, which should be prim */ 4649 switch (instField->field.signature[0]) { 4650 case 'D': 4651 case 'J': 4652 /* these are okay (and interchangeable) */ 4653 break; 4654 default: 4655 LOG_VFY("VFY: invalid iput-wide of %s.%s\n", 4656 instField->field.clazz->descriptor, 4657 instField->field.name); 4658 failure = VERIFY_ERROR_GENERIC; 4659 break; 4660 } 4661 } 4662 break; 4663 case OP_IPUT_OBJECT: 4664 case OP_IPUT_OBJECT_VOLATILE: 4665 { 4666 ClassObject* fieldClass; 4667 ClassObject* valueClass; 4668 InstField* instField; 4669 RegType objType, valueType; 4670 4671 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB, 4672 &failure); 4673 if (!VERIFY_OK(failure)) 4674 break; 4675 instField = getInstField(meth, uninitMap, objType, decInsn.vC, 4676 &failure); 4677 if (!VERIFY_OK(failure)) 4678 break; 4679 checkFinalFieldAccess(meth, &instField->field, &failure); 4680 if (!VERIFY_OK(failure)) 4681 break; 4682 4683 fieldClass = getFieldClass(meth, &instField->field); 4684 if (fieldClass == NULL) { 4685 LOG_VFY("VFY: unable to recover field class from '%s'\n", 4686 instField->field.signature); 4687 failure = VERIFY_ERROR_GENERIC; 4688 break; 4689 } 4690 4691 valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA, 4692 &failure); 4693 if (!VERIFY_OK(failure)) 4694 break; 4695 if (!regTypeIsReference(valueType)) { 4696 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n", 4697 decInsn.vA, instField->field.name, 4698 fieldClass->descriptor); 4699 failure = VERIFY_ERROR_GENERIC; 4700 break; 4701 } 4702 if (valueType != kRegTypeZero) { 4703 valueClass = regTypeInitializedReferenceToClass(valueType); 4704 if (valueClass == NULL) { 4705 LOG_VFY("VFY: storing uninit ref v%d into ref field\n", 4706 decInsn.vA); 4707 failure = VERIFY_ERROR_GENERIC; 4708 break; 4709 } 4710 /* allow if field is any interface or field is base class */ 4711 if (!dvmIsInterfaceClass(fieldClass) && 4712 !dvmInstanceof(valueClass, fieldClass)) 4713 { 4714 LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)\n", 4715 valueClass->descriptor, fieldClass->descriptor, 4716 instField->field.clazz->descriptor, 4717 instField->field.name); 4718 failure = VERIFY_ERROR_GENERIC; 4719 break; 4720 } 4721 } 4722 } 4723 break; 4724 4725 case OP_SGET: 4726 case OP_SGET_VOLATILE: 4727 tmpType = kRegTypeInteger; 4728 goto sget_1nr_common; 4729 case OP_SGET_BOOLEAN: 4730 tmpType = kRegTypeBoolean; 4731 goto sget_1nr_common; 4732 case OP_SGET_BYTE: 4733 tmpType = kRegTypeByte; 4734 goto sget_1nr_common; 4735 case OP_SGET_CHAR: 4736 tmpType = kRegTypeChar; 4737 goto sget_1nr_common; 4738 case OP_SGET_SHORT: 4739 tmpType = kRegTypeShort; 4740 goto sget_1nr_common; 4741 sget_1nr_common: 4742 { 4743 StaticField* staticField; 4744 RegType fieldType; 4745 4746 staticField = getStaticField(meth, decInsn.vB, &failure); 4747 if (!VERIFY_OK(failure)) 4748 break; 4749 4750 /* 4751 * Make sure the field's type is compatible with expectation. 4752 * We can get ourselves into trouble if we mix & match loads 4753 * and stores with different widths, so rather than just checking 4754 * "canConvertTo1nr" we require that the field types have equal 4755 * widths. (We can't generally require an exact type match, 4756 * because e.g. "int" and "float" are interchangeable.) 4757 */ 4758 fieldType = primSigCharToRegType(staticField->field.signature[0]); 4759 if (!checkFieldArrayStore1nr(tmpType, fieldType)) { 4760 LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)\n", 4761 staticField->field.clazz->descriptor, 4762 staticField->field.name, tmpType, fieldType); 4763 failure = VERIFY_ERROR_GENERIC; 4764 break; 4765 } 4766 4767 setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType, 4768 &failure); 4769 } 4770 break; 4771 case OP_SGET_WIDE: 4772 case OP_SGET_WIDE_VOLATILE: 4773 { 4774 StaticField* staticField; 4775 RegType dstType; 4776 4777 staticField = getStaticField(meth, decInsn.vB, &failure); 4778 if (!VERIFY_OK(failure)) 4779 break; 4780 /* check the type, which should be prim */ 4781 switch (staticField->field.signature[0]) { 4782 case 'D': 4783 dstType = kRegTypeDoubleLo; 4784 break; 4785 case 'J': 4786 dstType = kRegTypeLongLo; 4787 break; 4788 default: 4789 LOG_VFY("VFY: invalid sget-wide of %s.%s\n", 4790 staticField->field.clazz->descriptor, 4791 staticField->field.name); 4792 dstType = kRegTypeUnknown; 4793 failure = VERIFY_ERROR_GENERIC; 4794 break; 4795 } 4796 if (VERIFY_OK(failure)) { 4797 setRegisterType(workRegs, insnRegCount, decInsn.vA, 4798 dstType, &failure); 4799 } 4800 } 4801 break; 4802 case OP_SGET_OBJECT: 4803 case OP_SGET_OBJECT_VOLATILE: 4804 { 4805 StaticField* staticField; 4806 ClassObject* fieldClass; 4807 4808 staticField = getStaticField(meth, decInsn.vB, &failure); 4809 if (!VERIFY_OK(failure)) 4810 break; 4811 fieldClass = getFieldClass(meth, &staticField->field); 4812 if (fieldClass == NULL) { 4813 LOG_VFY("VFY: unable to recover field class from '%s'\n", 4814 staticField->field.signature); 4815 failure = VERIFY_ERROR_GENERIC; 4816 break; 4817 } 4818 if (dvmIsPrimitiveClass(fieldClass)) { 4819 LOG_VFY("VFY: attempt to get prim field with sget-object\n"); 4820 failure = VERIFY_ERROR_GENERIC; 4821 break; 4822 } 4823 setRegisterType(workRegs, insnRegCount, decInsn.vA, 4824 regTypeFromClass(fieldClass), &failure); 4825 } 4826 break; 4827 case OP_SPUT: 4828 case OP_SPUT_VOLATILE: 4829 tmpType = kRegTypeInteger; 4830 goto sput_1nr_common; 4831 case OP_SPUT_BOOLEAN: 4832 tmpType = kRegTypeBoolean; 4833 goto sput_1nr_common; 4834 case OP_SPUT_BYTE: 4835 tmpType = kRegTypeByte; 4836 goto sput_1nr_common; 4837 case OP_SPUT_CHAR: 4838 tmpType = kRegTypeChar; 4839 goto sput_1nr_common; 4840 case OP_SPUT_SHORT: 4841 tmpType = kRegTypeShort; 4842 goto sput_1nr_common; 4843 sput_1nr_common: 4844 { 4845 RegType srcType, fieldType; 4846 StaticField* staticField; 4847 4848 srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA, 4849 &failure); 4850 4851 /* 4852 * javac generates synthetic functions that write byte values 4853 * into boolean fields. 4854 */ 4855 if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte) 4856 srcType = kRegTypeBoolean; 4857 4858 /* make sure the source register has the correct type */ 4859 if (!canConvertTo1nr(srcType, tmpType)) { 4860 LOG_VFY("VFY: invalid reg type %d on sput instr (need %d)\n", 4861 srcType, tmpType); 4862 failure = VERIFY_ERROR_GENERIC; 4863 break; 4864 } 4865 4866 staticField = getStaticField(meth, decInsn.vB, &failure); 4867 if (!VERIFY_OK(failure)) 4868 break; 4869 checkFinalFieldAccess(meth, &staticField->field, &failure); 4870 if (!VERIFY_OK(failure)) 4871 break; 4872 4873 /* 4874 * Get type of field we're storing into. We know that the 4875 * contents of the register match the instruction, but we also 4876 * need to ensure that the instruction matches the field type. 4877 * Using e.g. sput-short to write into a 32-bit integer field 4878 * can lead to trouble if we do 16-bit writes. 4879 */ 4880 fieldType = primSigCharToRegType(staticField->field.signature[0]); 4881 if (!checkFieldArrayStore1nr(tmpType, fieldType)) { 4882 LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)\n", 4883 staticField->field.clazz->descriptor, 4884 staticField->field.name, tmpType, fieldType); 4885 failure = VERIFY_ERROR_GENERIC; 4886 break; 4887 } 4888 } 4889 break; 4890 case OP_SPUT_WIDE: 4891 case OP_SPUT_WIDE_VOLATILE: 4892 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure); 4893 if (VERIFY_OK(failure)) { 4894 RegType typeHi = 4895 getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure); 4896 checkTypeCategory(tmpType, kTypeCategory2, &failure); 4897 checkWidePair(tmpType, typeHi, &failure); 4898 } 4899 if (VERIFY_OK(failure)) { 4900 StaticField* staticField; 4901 4902 staticField = getStaticField(meth, decInsn.vB, &failure); 4903 if (!VERIFY_OK(failure)) 4904 break; 4905 checkFinalFieldAccess(meth, &staticField->field, &failure); 4906 if (!VERIFY_OK(failure)) 4907 break; 4908 4909 /* check the type, which should be prim */ 4910 switch (staticField->field.signature[0]) { 4911 case 'D': 4912 case 'J': 4913 /* these are okay */ 4914 break; 4915 default: 4916 LOG_VFY("VFY: invalid sput-wide of %s.%s\n", 4917 staticField->field.clazz->descriptor, 4918 staticField->field.name); 4919 failure = VERIFY_ERROR_GENERIC; 4920 break; 4921 } 4922 } 4923 break; 4924 case OP_SPUT_OBJECT: 4925 case OP_SPUT_OBJECT_VOLATILE: 4926 { 4927 ClassObject* fieldClass; 4928 ClassObject* valueClass; 4929 StaticField* staticField; 4930 RegType valueType; 4931 4932 staticField = getStaticField(meth, decInsn.vB, &failure); 4933 if (!VERIFY_OK(failure)) 4934 break; 4935 checkFinalFieldAccess(meth, &staticField->field, &failure); 4936 if (!VERIFY_OK(failure)) 4937 break; 4938 4939 fieldClass = getFieldClass(meth, &staticField->field); 4940 if (fieldClass == NULL) { 4941 LOG_VFY("VFY: unable to recover field class from '%s'\n", 4942 staticField->field.signature); 4943 failure = VERIFY_ERROR_GENERIC; 4944 break; 4945 } 4946 4947 valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA, 4948 &failure); 4949 if (!VERIFY_OK(failure)) 4950 break; 4951 if (!regTypeIsReference(valueType)) { 4952 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n", 4953 decInsn.vA, staticField->field.name, 4954 fieldClass->descriptor); 4955 failure = VERIFY_ERROR_GENERIC; 4956 break; 4957 } 4958 if (valueType != kRegTypeZero) { 4959 valueClass = regTypeInitializedReferenceToClass(valueType); 4960 if (valueClass == NULL) { 4961 LOG_VFY("VFY: storing uninit ref v%d into ref field\n", 4962 decInsn.vA); 4963 failure = VERIFY_ERROR_GENERIC; 4964 break; 4965 } 4966 /* allow if field is any interface or field is base class */ 4967 if (!dvmIsInterfaceClass(fieldClass) && 4968 !dvmInstanceof(valueClass, fieldClass)) 4969 { 4970 LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)\n", 4971 valueClass->descriptor, fieldClass->descriptor, 4972 staticField->field.clazz->descriptor, 4973 staticField->field.name); 4974 failure = VERIFY_ERROR_GENERIC; 4975 break; 4976 } 4977 } 4978 } 4979 break; 4980 4981 case OP_INVOKE_VIRTUAL: 4982 case OP_INVOKE_VIRTUAL_RANGE: 4983 case OP_INVOKE_SUPER: 4984 case OP_INVOKE_SUPER_RANGE: 4985 { 4986 Method* calledMethod; 4987 RegType returnType; 4988 bool isRange; 4989 bool isSuper; 4990 4991 isRange = (decInsn.opCode == OP_INVOKE_VIRTUAL_RANGE || 4992 decInsn.opCode == OP_INVOKE_SUPER_RANGE); 4993 isSuper = (decInsn.opCode == OP_INVOKE_SUPER || 4994 decInsn.opCode == OP_INVOKE_SUPER_RANGE); 4995 4996 calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount, 4997 &decInsn, uninitMap, METHOD_VIRTUAL, isRange, 4998 isSuper, &failure); 4999 if (!VERIFY_OK(failure)) 5000 break; 5001 returnType = getMethodReturnType(calledMethod); 5002 setResultRegisterType(workRegs, insnRegCount, returnType, &failure); 5003 justSetResult = true; 5004 } 5005 break; 5006 case OP_INVOKE_DIRECT: 5007 case OP_INVOKE_DIRECT_RANGE: 5008 { 5009 RegType returnType; 5010 Method* calledMethod; 5011 bool isRange; 5012 5013 isRange = (decInsn.opCode == OP_INVOKE_DIRECT_RANGE); 5014 calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount, 5015 &decInsn, uninitMap, METHOD_DIRECT, isRange, 5016 false, &failure); 5017 if (!VERIFY_OK(failure)) 5018 break; 5019 5020 /* 5021 * Some additional checks when calling <init>. We know from 5022 * the invocation arg check that the "this" argument is an 5023 * instance of calledMethod->clazz. Now we further restrict 5024 * that to require that calledMethod->clazz is the same as 5025 * this->clazz or this->super, allowing the latter only if 5026 * the "this" argument is the same as the "this" argument to 5027 * this method (which implies that we're in <init> ourselves). 5028 */ 5029 if (isInitMethod(calledMethod)) { 5030 RegType thisType; 5031 thisType = getInvocationThis(workRegs, insnRegCount, 5032 &decInsn, &failure); 5033 if (!VERIFY_OK(failure)) 5034 break; 5035 5036 /* no null refs allowed (?) */ 5037 if (thisType == kRegTypeZero) { 5038 LOG_VFY("VFY: unable to initialize null ref\n"); 5039 failure = VERIFY_ERROR_GENERIC; 5040 break; 5041 } 5042 5043 ClassObject* thisClass; 5044 5045 thisClass = regTypeReferenceToClass(thisType, uninitMap); 5046 assert(thisClass != NULL); 5047 5048 /* must be in same class or in superclass */ 5049 if (calledMethod->clazz == thisClass->super) { 5050 if (thisClass != meth->clazz) { 5051 LOG_VFY("VFY: invoke-direct <init> on super only " 5052 "allowed for 'this' in <init>"); 5053 failure = VERIFY_ERROR_GENERIC; 5054 break; 5055 } 5056 } else if (calledMethod->clazz != thisClass) { 5057 LOG_VFY("VFY: invoke-direct <init> must be on current " 5058 "class or super\n"); 5059 failure = VERIFY_ERROR_GENERIC; 5060 break; 5061 } 5062 5063 /* arg must be an uninitialized reference */ 5064 if (!regTypeIsUninitReference(thisType)) { 5065 LOG_VFY("VFY: can only initialize the uninitialized\n"); 5066 failure = VERIFY_ERROR_GENERIC; 5067 break; 5068 } 5069 5070 /* 5071 * Replace the uninitialized reference with an initialized 5072 * one, and clear the entry in the uninit map. We need to 5073 * do this for all registers that have the same object 5074 * instance in them, not just the "this" register. 5075 */ 5076 markRefsAsInitialized(workRegs, insnRegCount, uninitMap, 5077 thisType, &failure); 5078 if (!VERIFY_OK(failure)) 5079 break; 5080 } 5081 returnType = getMethodReturnType(calledMethod); 5082 setResultRegisterType(workRegs, insnRegCount, 5083 returnType, &failure); 5084 justSetResult = true; 5085 } 5086 break; 5087 case OP_INVOKE_STATIC: 5088 case OP_INVOKE_STATIC_RANGE: 5089 { 5090 RegType returnType; 5091 Method* calledMethod; 5092 bool isRange; 5093 5094 isRange = (decInsn.opCode == OP_INVOKE_STATIC_RANGE); 5095 calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount, 5096 &decInsn, uninitMap, METHOD_STATIC, isRange, 5097 false, &failure); 5098 if (!VERIFY_OK(failure)) 5099 break; 5100 5101 returnType = getMethodReturnType(calledMethod); 5102 setResultRegisterType(workRegs, insnRegCount, returnType, &failure); 5103 justSetResult = true; 5104 } 5105 break; 5106 case OP_INVOKE_INTERFACE: 5107 case OP_INVOKE_INTERFACE_RANGE: 5108 { 5109 RegType /*thisType,*/ returnType; 5110 Method* absMethod; 5111 bool isRange; 5112 5113 isRange = (decInsn.opCode == OP_INVOKE_INTERFACE_RANGE); 5114 absMethod = verifyInvocationArgs(meth, workRegs, insnRegCount, 5115 &decInsn, uninitMap, METHOD_INTERFACE, isRange, 5116 false, &failure); 5117 if (!VERIFY_OK(failure)) 5118 break; 5119 5120 #if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */ 5121 /* 5122 * Get the type of the "this" arg, which should always be an 5123 * interface class. Because we don't do a full merge on 5124 * interface classes, this might have reduced to Object. 5125 */ 5126 thisType = getInvocationThis(workRegs, insnRegCount, 5127 &decInsn, &failure); 5128 if (!VERIFY_OK(failure)) 5129 break; 5130 5131 if (thisType == kRegTypeZero) { 5132 /* null pointer always passes (and always fails at runtime) */ 5133 } else { 5134 ClassObject* thisClass; 5135 5136 thisClass = regTypeInitializedReferenceToClass(thisType); 5137 if (thisClass == NULL) { 5138 LOG_VFY("VFY: interface call on uninitialized\n"); 5139 failure = VERIFY_ERROR_GENERIC; 5140 break; 5141 } 5142 5143 /* 5144 * Either "thisClass" needs to be the interface class that 5145 * defined absMethod, or absMethod's class needs to be one 5146 * of the interfaces implemented by "thisClass". (Or, if 5147 * we couldn't complete the merge, this will be Object.) 5148 */ 5149 if (thisClass != absMethod->clazz && 5150 thisClass != gDvm.classJavaLangObject && 5151 !dvmImplements(thisClass, absMethod->clazz)) 5152 { 5153 LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces\n", 5154 absMethod->name, thisClass->descriptor); 5155 failure = VERIFY_ERROR_GENERIC; 5156 break; 5157 } 5158 } 5159 #endif 5160 5161 /* 5162 * We don't have an object instance, so we can't find the 5163 * concrete method. However, all of the type information is 5164 * in the abstract method, so we're good. 5165 */ 5166 returnType = getMethodReturnType(absMethod); 5167 setResultRegisterType(workRegs, insnRegCount, returnType, &failure); 5168 justSetResult = true; 5169 } 5170 break; 5171 5172 case OP_NEG_INT: 5173 case OP_NOT_INT: 5174 checkUnop(workRegs, insnRegCount, &decInsn, 5175 kRegTypeInteger, kRegTypeInteger, &failure); 5176 break; 5177 case OP_NEG_LONG: 5178 case OP_NOT_LONG: 5179 checkUnop(workRegs, insnRegCount, &decInsn, 5180 kRegTypeLongLo, kRegTypeLongLo, &failure); 5181 break; 5182 case OP_NEG_FLOAT: 5183 checkUnop(workRegs, insnRegCount, &decInsn, 5184 kRegTypeFloat, kRegTypeFloat, &failure); 5185 break; 5186 case OP_NEG_DOUBLE: 5187 checkUnop(workRegs, insnRegCount, &decInsn, 5188 kRegTypeDoubleLo, kRegTypeDoubleLo, &failure); 5189 break; 5190 case OP_INT_TO_LONG: 5191 checkUnop(workRegs, insnRegCount, &decInsn, 5192 kRegTypeLongLo, kRegTypeInteger, &failure); 5193 break; 5194 case OP_INT_TO_FLOAT: 5195 checkUnop(workRegs, insnRegCount, &decInsn, 5196 kRegTypeFloat, kRegTypeInteger, &failure); 5197 break; 5198 case OP_INT_TO_DOUBLE: 5199 checkUnop(workRegs, insnRegCount, &decInsn, 5200 kRegTypeDoubleLo, kRegTypeInteger, &failure); 5201 break; 5202 case OP_LONG_TO_INT: 5203 checkUnop(workRegs, insnRegCount, &decInsn, 5204 kRegTypeInteger, kRegTypeLongLo, &failure); 5205 break; 5206 case OP_LONG_TO_FLOAT: 5207 checkUnop(workRegs, insnRegCount, &decInsn, 5208 kRegTypeFloat, kRegTypeLongLo, &failure); 5209 break; 5210 case OP_LONG_TO_DOUBLE: 5211 checkUnop(workRegs, insnRegCount, &decInsn, 5212 kRegTypeDoubleLo, kRegTypeLongLo, &failure); 5213 break; 5214 case OP_FLOAT_TO_INT: 5215 checkUnop(workRegs, insnRegCount, &decInsn, 5216 kRegTypeInteger, kRegTypeFloat, &failure); 5217 break; 5218 case OP_FLOAT_TO_LONG: 5219 checkUnop(workRegs, insnRegCount, &decInsn, 5220 kRegTypeLongLo, kRegTypeFloat, &failure); 5221 break; 5222 case OP_FLOAT_TO_DOUBLE: 5223 checkUnop(workRegs, insnRegCount, &decInsn, 5224 kRegTypeDoubleLo, kRegTypeFloat, &failure); 5225 break; 5226 case OP_DOUBLE_TO_INT: 5227 checkUnop(workRegs, insnRegCount, &decInsn, 5228 kRegTypeInteger, kRegTypeDoubleLo, &failure); 5229 break; 5230 case OP_DOUBLE_TO_LONG: 5231 checkUnop(workRegs, insnRegCount, &decInsn, 5232 kRegTypeLongLo, kRegTypeDoubleLo, &failure); 5233 break; 5234 case OP_DOUBLE_TO_FLOAT: 5235 checkUnop(workRegs, insnRegCount, &decInsn, 5236 kRegTypeFloat, kRegTypeDoubleLo, &failure); 5237 break; 5238 case OP_INT_TO_BYTE: 5239 checkUnop(workRegs, insnRegCount, &decInsn, 5240 kRegTypeByte, kRegTypeInteger, &failure); 5241 break; 5242 case OP_INT_TO_CHAR: 5243 checkUnop(workRegs, insnRegCount, &decInsn, 5244 kRegTypeChar, kRegTypeInteger, &failure); 5245 break; 5246 case OP_INT_TO_SHORT: 5247 checkUnop(workRegs, insnRegCount, &decInsn, 5248 kRegTypeShort, kRegTypeInteger, &failure); 5249 break; 5250 5251 case OP_ADD_INT: 5252 case OP_SUB_INT: 5253 case OP_MUL_INT: 5254 case OP_REM_INT: 5255 case OP_DIV_INT: 5256 case OP_SHL_INT: 5257 case OP_SHR_INT: 5258 case OP_USHR_INT: 5259 checkBinop(workRegs, insnRegCount, &decInsn, 5260 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure); 5261 break; 5262 case OP_AND_INT: 5263 case OP_OR_INT: 5264 case OP_XOR_INT: 5265 checkBinop(workRegs, insnRegCount, &decInsn, 5266 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure); 5267 break; 5268 case OP_ADD_LONG: 5269 case OP_SUB_LONG: 5270 case OP_MUL_LONG: 5271 case OP_DIV_LONG: 5272 case OP_REM_LONG: 5273 case OP_AND_LONG: 5274 case OP_OR_LONG: 5275 case OP_XOR_LONG: 5276 checkBinop(workRegs, insnRegCount, &decInsn, 5277 kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure); 5278 break; 5279 case OP_SHL_LONG: 5280 case OP_SHR_LONG: 5281 case OP_USHR_LONG: 5282 /* shift distance is Int, making these different from other binops */ 5283 checkBinop(workRegs, insnRegCount, &decInsn, 5284 kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure); 5285 break; 5286 case OP_ADD_FLOAT: 5287 case OP_SUB_FLOAT: 5288 case OP_MUL_FLOAT: 5289 case OP_DIV_FLOAT: 5290 case OP_REM_FLOAT: 5291 checkBinop(workRegs, insnRegCount, &decInsn, 5292 kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure); 5293 break; 5294 case OP_ADD_DOUBLE: 5295 case OP_SUB_DOUBLE: 5296 case OP_MUL_DOUBLE: 5297 case OP_DIV_DOUBLE: 5298 case OP_REM_DOUBLE: 5299 checkBinop(workRegs, insnRegCount, &decInsn, 5300 kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, 5301 &failure); 5302 break; 5303 case OP_ADD_INT_2ADDR: 5304 case OP_SUB_INT_2ADDR: 5305 case OP_MUL_INT_2ADDR: 5306 case OP_REM_INT_2ADDR: 5307 case OP_SHL_INT_2ADDR: 5308 case OP_SHR_INT_2ADDR: 5309 case OP_USHR_INT_2ADDR: 5310 checkBinop2addr(workRegs, insnRegCount, &decInsn, 5311 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure); 5312 break; 5313 case OP_AND_INT_2ADDR: 5314 case OP_OR_INT_2ADDR: 5315 case OP_XOR_INT_2ADDR: 5316 checkBinop2addr(workRegs, insnRegCount, &decInsn, 5317 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure); 5318 break; 5319 case OP_DIV_INT_2ADDR: 5320 checkBinop2addr(workRegs, insnRegCount, &decInsn, 5321 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure); 5322 break; 5323 case OP_ADD_LONG_2ADDR: 5324 case OP_SUB_LONG_2ADDR: 5325 case OP_MUL_LONG_2ADDR: 5326 case OP_DIV_LONG_2ADDR: 5327 case OP_REM_LONG_2ADDR: 5328 case OP_AND_LONG_2ADDR: 5329 case OP_OR_LONG_2ADDR: 5330 case OP_XOR_LONG_2ADDR: 5331 checkBinop2addr(workRegs, insnRegCount, &decInsn, 5332 kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure); 5333 break; 5334 case OP_SHL_LONG_2ADDR: 5335 case OP_SHR_LONG_2ADDR: 5336 case OP_USHR_LONG_2ADDR: 5337 checkBinop2addr(workRegs, insnRegCount, &decInsn, 5338 kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure); 5339 break; 5340 case OP_ADD_FLOAT_2ADDR: 5341 case OP_SUB_FLOAT_2ADDR: 5342 case OP_MUL_FLOAT_2ADDR: 5343 case OP_DIV_FLOAT_2ADDR: 5344 case OP_REM_FLOAT_2ADDR: 5345 checkBinop2addr(workRegs, insnRegCount, &decInsn, 5346 kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure); 5347 break; 5348 case OP_ADD_DOUBLE_2ADDR: 5349 case OP_SUB_DOUBLE_2ADDR: 5350 case OP_MUL_DOUBLE_2ADDR: 5351 case OP_DIV_DOUBLE_2ADDR: 5352 case OP_REM_DOUBLE_2ADDR: 5353 checkBinop2addr(workRegs, insnRegCount, &decInsn, 5354 kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false, 5355 &failure); 5356 break; 5357 case OP_ADD_INT_LIT16: 5358 case OP_RSUB_INT: 5359 case OP_MUL_INT_LIT16: 5360 case OP_DIV_INT_LIT16: 5361 case OP_REM_INT_LIT16: 5362 checkLitop(workRegs, insnRegCount, &decInsn, 5363 kRegTypeInteger, kRegTypeInteger, false, &failure); 5364 break; 5365 case OP_AND_INT_LIT16: 5366 case OP_OR_INT_LIT16: 5367 case OP_XOR_INT_LIT16: 5368 checkLitop(workRegs, insnRegCount, &decInsn, 5369 kRegTypeInteger, kRegTypeInteger, true, &failure); 5370 break; 5371 case OP_ADD_INT_LIT8: 5372 case OP_RSUB_INT_LIT8: 5373 case OP_MUL_INT_LIT8: 5374 case OP_DIV_INT_LIT8: 5375 case OP_REM_INT_LIT8: 5376 case OP_SHL_INT_LIT8: 5377 checkLitop(workRegs, insnRegCount, &decInsn, 5378 kRegTypeInteger, kRegTypeInteger, false, &failure); 5379 break; 5380 case OP_SHR_INT_LIT8: 5381 tmpType = adjustForRightShift(workRegs, insnRegCount, 5382 decInsn.vB, decInsn.vC, false, &failure); 5383 checkLitop(workRegs, insnRegCount, &decInsn, 5384 tmpType, kRegTypeInteger, false, &failure); 5385 break; 5386 case OP_USHR_INT_LIT8: 5387 tmpType = adjustForRightShift(workRegs, insnRegCount, 5388 decInsn.vB, decInsn.vC, true, &failure); 5389 checkLitop(workRegs, insnRegCount, &decInsn, 5390 tmpType, kRegTypeInteger, false, &failure); 5391 break; 5392 case OP_AND_INT_LIT8: 5393 case OP_OR_INT_LIT8: 5394 case OP_XOR_INT_LIT8: 5395 checkLitop(workRegs, insnRegCount, &decInsn, 5396 kRegTypeInteger, kRegTypeInteger, true, &failure); 5397 break; 5398 5399 /* 5400 * This falls into the general category of "optimized" instructions, 5401 * which don't generally appear during verification. Because it's 5402 * inserted in the course of verification, we can expect to see it here. 5403 */ 5404 case OP_THROW_VERIFICATION_ERROR: 5405 break; 5406 5407 /* 5408 * Verifying "quickened" instructions is tricky, because we have 5409 * discarded the original field/method information. The byte offsets 5410 * and vtable indices only have meaning in the context of an object 5411 * instance. 5412 * 5413 * If a piece of code declares a local reference variable, assigns 5414 * null to it, and then issues a virtual method call on it, we 5415 * cannot evaluate the method call during verification. This situation 5416 * isn't hard to handle, since we know the call will always result in an 5417 * NPE, and the arguments and return value don't matter. Any code that 5418 * depends on the result of the method call is inaccessible, so the 5419 * fact that we can't fully verify anything that comes after the bad 5420 * call is not a problem. 5421 * 5422 * We must also consider the case of multiple code paths, only some of 5423 * which involve a null reference. We can completely verify the method 5424 * if we sidestep the results of executing with a null reference. 5425 * For example, if on the first pass through the code we try to do a 5426 * virtual method invocation through a null ref, we have to skip the 5427 * method checks and have the method return a "wildcard" type (which 5428 * merges with anything to become that other thing). The move-result 5429 * will tell us if it's a reference, single-word numeric, or double-word 5430 * value. We continue to perform the verification, and at the end of 5431 * the function any invocations that were never fully exercised are 5432 * marked as null-only. 5433 * 5434 * We would do something similar for the field accesses. The field's 5435 * type, once known, can be used to recover the width of short integers. 5436 * If the object reference was null, the field-get returns the "wildcard" 5437 * type, which is acceptable for any operation. 5438 */ 5439 case OP_EXECUTE_INLINE: 5440 case OP_EXECUTE_INLINE_RANGE: 5441 case OP_INVOKE_DIRECT_EMPTY: 5442 case OP_IGET_QUICK: 5443 case OP_IGET_WIDE_QUICK: 5444 case OP_IGET_OBJECT_QUICK: 5445 case OP_IPUT_QUICK: 5446 case OP_IPUT_WIDE_QUICK: 5447 case OP_IPUT_OBJECT_QUICK: 5448 case OP_INVOKE_VIRTUAL_QUICK: 5449 case OP_INVOKE_VIRTUAL_QUICK_RANGE: 5450 case OP_INVOKE_SUPER_QUICK: 5451 case OP_INVOKE_SUPER_QUICK_RANGE: 5452 failure = VERIFY_ERROR_GENERIC; 5453 break; 5454 5455 /* these should never appear during verification */ 5456 case OP_UNUSED_3E: 5457 case OP_UNUSED_3F: 5458 case OP_UNUSED_40: 5459 case OP_UNUSED_41: 5460 case OP_UNUSED_42: 5461 case OP_UNUSED_43: 5462 case OP_UNUSED_73: 5463 case OP_UNUSED_79: 5464 case OP_UNUSED_7A: 5465 case OP_BREAKPOINT: 5466 case OP_UNUSED_F1: 5467 case OP_UNUSED_FF: 5468 failure = VERIFY_ERROR_GENERIC; 5469 break; 5470 5471 /* 5472 * DO NOT add a "default" clause here. Without it the compiler will 5473 * complain if an instruction is missing (which is desirable). 5474 */ 5475 } 5476 5477 if (!VERIFY_OK(failure)) { 5478 if (failure == VERIFY_ERROR_GENERIC || gDvm.optimizing) { 5479 /* immediate failure, reject class */ 5480 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x\n", 5481 decInsn.opCode, insnIdx); 5482 goto bail; 5483 } else { 5484 /* replace opcode and continue on */ 5485 LOGD("VFY: replacing opcode 0x%02x at 0x%04x\n", 5486 decInsn.opCode, insnIdx); 5487 if (!replaceFailingInstruction(meth, insnFlags, insnIdx, failure)) { 5488 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x\n", 5489 decInsn.opCode, insnIdx); 5490 goto bail; 5491 } 5492 /* IMPORTANT: meth->insns may have been changed */ 5493 insns = meth->insns + insnIdx; 5494 5495 /* continue on as if we just handled a throw-verification-error */ 5496 failure = VERIFY_ERROR_NONE; 5497 nextFlags = kInstrCanThrow; 5498 } 5499 } 5500 5501 /* 5502 * If we didn't just set the result register, clear it out. This 5503 * ensures that you can only use "move-result" immediately after the 5504 * result is set. (We could check this statically, but it's not 5505 * expensive and it makes our debugging output cleaner.) 5506 */ 5507 if (!justSetResult) { 5508 int reg = RESULT_REGISTER(insnRegCount); 5509 workRegs[reg] = workRegs[reg+1] = kRegTypeUnknown; 5510 } 5511 5512 /* 5513 * Handle "continue". Tag the next consecutive instruction. 5514 */ 5515 if ((nextFlags & kInstrCanContinue) != 0) { 5516 int insnWidth = dvmInsnGetWidth(insnFlags, insnIdx); 5517 if (insnIdx+insnWidth >= insnsSize) { 5518 LOG_VFY_METH(meth, 5519 "VFY: execution can walk off end of code area (from 0x%x)\n", 5520 insnIdx); 5521 goto bail; 5522 } 5523 5524 /* 5525 * The only way to get to a move-exception instruction is to get 5526 * thrown there. Make sure the next instruction isn't one. 5527 */ 5528 if (!checkMoveException(meth, insnIdx+insnWidth, "next")) 5529 goto bail; 5530 5531 if (getRegisterLine(regTable, insnIdx+insnWidth) != NULL) { 5532 /* 5533 * Merge registers into what we have for the next instruction, 5534 * and set the "changed" flag if needed. 5535 */ 5536 updateRegisters(meth, insnFlags, regTable, insnIdx+insnWidth, 5537 workRegs); 5538 } else { 5539 /* 5540 * We're not recording register data for the next instruction, 5541 * so we don't know what the prior state was. We have to 5542 * assume that something has changed and re-evaluate it. 5543 */ 5544 dvmInsnSetChanged(insnFlags, insnIdx+insnWidth, true); 5545 } 5546 } 5547 5548 /* 5549 * Handle "branch". Tag the branch target. 5550 * 5551 * NOTE: instructions like OP_EQZ provide information about the state 5552 * of the register when the branch is taken or not taken. For example, 5553 * somebody could get a reference field, check it for zero, and if the 5554 * branch is taken immediately store that register in a boolean field 5555 * since the value is known to be zero. We do not currently account for 5556 * that, and will reject the code. 5557 */ 5558 if ((nextFlags & kInstrCanBranch) != 0) { 5559 bool isConditional; 5560 5561 if (!dvmGetBranchTarget(meth, insnFlags, insnIdx, &branchTarget, 5562 &isConditional)) 5563 { 5564 /* should never happen after static verification */ 5565 LOG_VFY_METH(meth, "VFY: bad branch at %d\n", insnIdx); 5566 goto bail; 5567 } 5568 assert(isConditional || (nextFlags & kInstrCanContinue) == 0); 5569 assert(!isConditional || (nextFlags & kInstrCanContinue) != 0); 5570 5571 if (!checkMoveException(meth, insnIdx+branchTarget, "branch")) 5572 goto bail; 5573 5574 /* update branch target, set "changed" if appropriate */ 5575 updateRegisters(meth, insnFlags, regTable, insnIdx+branchTarget, 5576 workRegs); 5577 } 5578 5579 /* 5580 * Handle "switch". Tag all possible branch targets. 5581 * 5582 * We've already verified that the table is structurally sound, so we 5583 * just need to walk through and tag the targets. 5584 */ 5585 if ((nextFlags & kInstrCanSwitch) != 0) { 5586 int offsetToSwitch = insns[1] | (((s4)insns[2]) << 16); 5587 const u2* switchInsns = insns + offsetToSwitch; 5588 int switchCount = switchInsns[1]; 5589 int offsetToTargets, targ; 5590 5591 if ((*insns & 0xff) == OP_PACKED_SWITCH) { 5592 /* 0=sig, 1=count, 2/3=firstKey */ 5593 offsetToTargets = 4; 5594 } else { 5595 /* 0=sig, 1=count, 2..count*2 = keys */ 5596 assert((*insns & 0xff) == OP_SPARSE_SWITCH); 5597 offsetToTargets = 2 + 2*switchCount; 5598 } 5599 5600 /* verify each switch target */ 5601 for (targ = 0; targ < switchCount; targ++) { 5602 int offset, absOffset; 5603 5604 /* offsets are 32-bit, and only partly endian-swapped */ 5605 offset = switchInsns[offsetToTargets + targ*2] | 5606 (((s4) switchInsns[offsetToTargets + targ*2 +1]) << 16); 5607 absOffset = insnIdx + offset; 5608 5609 assert(absOffset >= 0 && absOffset < insnsSize); 5610 5611 if (!checkMoveException(meth, absOffset, "switch")) 5612 goto bail; 5613 5614 updateRegisters(meth, insnFlags, regTable, absOffset, workRegs); 5615 } 5616 } 5617 5618 /* 5619 * Handle instructions that can throw and that are sitting in a 5620 * "try" block. (If they're not in a "try" block when they throw, 5621 * control transfers out of the method.) 5622 */ 5623 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx)) 5624 { 5625 const DexCode* pCode = dvmGetMethodCode(meth); 5626 DexCatchIterator iterator; 5627 5628 if (dexFindCatchHandler(&iterator, pCode, insnIdx)) { 5629 for (;;) { 5630 DexCatchHandler* handler = dexCatchIteratorNext(&iterator); 5631 5632 if (handler == NULL) { 5633 break; 5634 } 5635 5636 /* note we use entryRegs, not workRegs */ 5637 updateRegisters(meth, insnFlags, regTable, handler->address, 5638 entryRegs); 5639 } 5640 } 5641 } 5642 5643 /* 5644 * Update startGuess. Advance to the next instruction of that's 5645 * possible, otherwise use the branch target if one was found. If 5646 * neither of those exists we're in a return or throw; leave startGuess 5647 * alone and let the caller sort it out. 5648 */ 5649 if ((nextFlags & kInstrCanContinue) != 0) { 5650 *pStartGuess = insnIdx + dvmInsnGetWidth(insnFlags, insnIdx); 5651 } else if ((nextFlags & kInstrCanBranch) != 0) { 5652 /* we're still okay if branchTarget is zero */ 5653 *pStartGuess = insnIdx + branchTarget; 5654 } 5655 5656 assert(*pStartGuess >= 0 && *pStartGuess < insnsSize && 5657 dvmInsnGetWidth(insnFlags, *pStartGuess) != 0); 5658 5659 result = true; 5660 5661 bail: 5662 return result; 5663 } 5664 5665 5666 /* 5667 * callback function used in dumpRegTypes to print local vars 5668 * valid at a given address. 5669 */ 5670 static void logLocalsCb(void *cnxt, u2 reg, u4 startAddress, u4 endAddress, 5671 const char *name, const char *descriptor, 5672 const char *signature) 5673 { 5674 int addr = *((int *)cnxt); 5675 5676 if (addr >= (int) startAddress && addr < (int) endAddress) 5677 { 5678 LOGI(" %2d: '%s' %s\n", reg, name, descriptor); 5679 } 5680 } 5681 5682 /* 5683 * Dump the register types for the specifed address to the log file. 5684 */ 5685 static void dumpRegTypes(const Method* meth, const InsnFlags* insnFlags, 5686 const RegType* addrRegs, int addr, const char* addrName, 5687 const UninitInstanceMap* uninitMap, int displayFlags) 5688 { 5689 int regCount = meth->registersSize; 5690 int fullRegCount = regCount + kExtraRegs; 5691 bool branchTarget = dvmInsnIsBranchTarget(insnFlags, addr); 5692 int i; 5693 5694 assert(addr >= 0 && addr < (int) dvmGetMethodInsnsSize(meth)); 5695 5696 int regCharSize = fullRegCount + (fullRegCount-1)/4 + 2 +1; 5697 char regChars[regCharSize +1]; 5698 memset(regChars, ' ', regCharSize); 5699 regChars[0] = '['; 5700 if (regCount == 0) 5701 regChars[1] = ']'; 5702 else 5703 regChars[1 + (regCount-1) + (regCount-1)/4 +1] = ']'; 5704 regChars[regCharSize] = '\0'; 5705 5706 //const RegType* addrRegs = getRegisterLine(regTable, addr); 5707 5708 for (i = 0; i < regCount + kExtraRegs; i++) { 5709 char tch; 5710 5711 switch (addrRegs[i]) { 5712 case kRegTypeUnknown: tch = '.'; break; 5713 case kRegTypeConflict: tch = 'X'; break; 5714 case kRegTypeFloat: tch = 'F'; break; 5715 case kRegTypeZero: tch = '0'; break; 5716 case kRegTypeOne: tch = '1'; break; 5717 case kRegTypeBoolean: tch = 'Z'; break; 5718 case kRegTypePosByte: tch = 'b'; break; 5719 case kRegTypeByte: tch = 'B'; break; 5720 case kRegTypePosShort: tch = 's'; break; 5721 case kRegTypeShort: tch = 'S'; break; 5722 case kRegTypeChar: tch = 'C'; break; 5723 case kRegTypeInteger: tch = 'I'; break; 5724 case kRegTypeLongLo: tch = 'J'; break; 5725 case kRegTypeLongHi: tch = 'j'; break; 5726 case kRegTypeDoubleLo: tch = 'D'; break; 5727 case kRegTypeDoubleHi: tch = 'd'; break; 5728 default: 5729 if (regTypeIsReference(addrRegs[i])) { 5730 if (regTypeIsUninitReference(addrRegs[i])) 5731 tch = 'U'; 5732 else 5733 tch = 'L'; 5734 } else { 5735 tch = '*'; 5736 assert(false); 5737 } 5738 break; 5739 } 5740 5741 if (i < regCount) 5742 regChars[1 + i + (i/4)] = tch; 5743 else 5744 regChars[1 + i + (i/4) + 2] = tch; 5745 } 5746 5747 if (addr == 0 && addrName != NULL) 5748 LOGI("%c%s %s\n", branchTarget ? '>' : ' ', addrName, regChars); 5749 else 5750 LOGI("%c0x%04x %s\n", branchTarget ? '>' : ' ', addr, regChars); 5751 5752 if (displayFlags & DRT_SHOW_REF_TYPES) { 5753 for (i = 0; i < regCount + kExtraRegs; i++) { 5754 if (regTypeIsReference(addrRegs[i]) && addrRegs[i] != kRegTypeZero) 5755 { 5756 ClassObject* clazz; 5757 5758 clazz = regTypeReferenceToClass(addrRegs[i], uninitMap); 5759 assert(dvmValidateObject((Object*)clazz)); 5760 if (i < regCount) { 5761 LOGI(" %2d: 0x%08x %s%s\n", 5762 i, addrRegs[i], 5763 regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "", 5764 clazz->descriptor); 5765 } else { 5766 LOGI(" RS: 0x%08x %s%s\n", 5767 addrRegs[i], 5768 regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "", 5769 clazz->descriptor); 5770 } 5771 } 5772 } 5773 } 5774 if (displayFlags & DRT_SHOW_LOCALS) { 5775 dexDecodeDebugInfo(meth->clazz->pDvmDex->pDexFile, 5776 dvmGetMethodCode(meth), 5777 meth->clazz->descriptor, 5778 meth->prototype.protoIdx, 5779 meth->accessFlags, 5780 NULL, logLocalsCb, &addr); 5781 } 5782 } 5783