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