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