OSDN Git Service

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