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