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