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