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