CodeVerify.cpp revision 5a459d4a923cd2160026cc58e4d3da0858028320
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            LOGV("VFY: unable to find class referenced in signature (%s)",
639                pDescriptor);
640        } else {
641            LOG_VFY("VFY: unable to find class referenced in signature (%s)",
642                pDescriptor);
643        }
644
645        if (pDescriptor[0] == '[') {
646            /* We are looking at an array descriptor. */
647
648            /*
649             * There should never be a problem loading primitive arrays.
650             */
651            if (pDescriptor[1] != 'L' && pDescriptor[1] != '[') {
652                LOG_VFY("VFY: invalid char in signature in '%s'",
653                    pDescriptor);
654                *pFailure = VERIFY_ERROR_GENERIC;
655            }
656
657            /*
658             * Try to continue with base array type.  This will let
659             * us pass basic stuff (e.g. get array len) that wouldn't
660             * fly with an Object.  This is NOT correct if the
661             * missing type is a primitive array, but we should never
662             * have a problem loading those.  (I'm not convinced this
663             * is correct or even useful.  Just use Object here?)
664             */
665            clazz = dvmFindClassNoInit("[Ljava/lang/Object;",
666                meth->clazz->classLoader);
667        } else if (pDescriptor[0] == 'L') {
668            /*
669             * We are looking at a non-array reference descriptor;
670             * try to continue with base reference type.
671             */
672            clazz = gDvm.classJavaLangObject;
673        } else {
674            /* We are looking at a primitive type. */
675            LOG_VFY("VFY: invalid char in signature in '%s'", pDescriptor);
676            *pFailure = VERIFY_ERROR_GENERIC;
677        }
678
679        if (clazz == NULL) {
680            *pFailure = VERIFY_ERROR_GENERIC;
681        }
682    }
683
684    if (dvmIsPrimitiveClass(clazz)) {
685        LOG_VFY("VFY: invalid use of primitive type '%s'", pDescriptor);
686        *pFailure = VERIFY_ERROR_GENERIC;
687        clazz = NULL;
688    }
689
690    return clazz;
691}
692
693/*
694 * Look up a class reference in a signature.  Could be an arg or the
695 * return value.
696 *
697 * Advances "*pSig" to the last character in the signature (that is, to
698 * the ';').
699 *
700 * NOTE: this is also expected to verify the signature.
701 */
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        LOGV("VFY: unable to find class '%s' for field %s.%s, trying Object",
1392            field->signature, meth->clazz->descriptor, field->name);
1393        fieldClass = gDvm.classJavaLangObject;
1394    } else {
1395        assert(!dvmIsPrimitiveClass(fieldClass));
1396    }
1397    return fieldClass;
1398}
1399
1400
1401/*
1402 * ===========================================================================
1403 *      Register operations
1404 * ===========================================================================
1405 */
1406
1407/*
1408 * Get the type of register N.
1409 *
1410 * The register index was validated during the static pass, so we don't
1411 * need to check it here.
1412 */
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.  We could
2837         * do something special if we can definitively identify it as a
2838         * float, but there's no real value in doing so.
2839         */
2840        checkTypeCategory(regType, kTypeCategory1nr, pFailure);
2841        if (!VERIFY_OK(*pFailure)) {
2842            LOG_VFY_METH(meth, "Invalid reg type for array index (%d)",
2843                regType);
2844        }
2845    }
2846}
2847
2848/*
2849 * Check constraints on constructor return.  Specifically, make sure that
2850 * the "this" argument got initialized.
2851 *
2852 * The "this" argument to <init> uses code offset kUninitThisArgAddr, which
2853 * puts it at the start of the list in slot 0.  If we see a register with
2854 * an uninitialized slot 0 reference, we know it somehow didn't get
2855 * initialized.
2856 *
2857 * Returns "true" if all is well.
2858 */
2859static bool checkConstructorReturn(const Method* meth,
2860    const RegisterLine* registerLine, const int insnRegCount)
2861{
2862    const RegType* insnRegs = registerLine->regTypes;
2863    int i;
2864
2865    if (!isInitMethod(meth))
2866        return true;
2867
2868    RegType uninitThis = regTypeFromUninitIndex(kUninitThisArgSlot);
2869
2870    for (i = 0; i < insnRegCount; i++) {
2871        if (insnRegs[i] == uninitThis) {
2872            LOG_VFY("VFY: <init> returning without calling superclass init");
2873            return false;
2874        }
2875    }
2876    return true;
2877}
2878
2879/*
2880 * Verify that the target instruction is not "move-exception".  It's important
2881 * that the only way to execute a move-exception is as the first instruction
2882 * of an exception handler.
2883 *
2884 * Returns "true" if all is well, "false" if the target instruction is
2885 * move-exception.
2886 */
2887static bool checkMoveException(const Method* meth, int insnIdx,
2888    const char* logNote)
2889{
2890    assert(insnIdx >= 0 && insnIdx < (int)dvmGetMethodInsnsSize(meth));
2891
2892    if ((meth->insns[insnIdx] & 0xff) == OP_MOVE_EXCEPTION) {
2893        LOG_VFY("VFY: invalid use of move-exception");
2894        return false;
2895    }
2896    return true;
2897}
2898
2899/*
2900 * For the "move-exception" instruction at "insnIdx", which must be at an
2901 * exception handler address, determine the first common superclass of
2902 * all exceptions that can land here.  (For javac output, we're probably
2903 * looking at multiple spans of bytecode covered by one "try" that lands
2904 * at an exception-specific "catch", but in general the handler could be
2905 * shared for multiple exceptions.)
2906 *
2907 * Returns NULL if no matching exception handler can be found, or if the
2908 * exception is not a subclass of Throwable.
2909 */
2910static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx,
2911    VerifyError* pFailure)
2912{
2913    VerifyError localFailure;
2914    const DexCode* pCode;
2915    DexFile* pDexFile;
2916    ClassObject* commonSuper = NULL;
2917    u4 handlersSize;
2918    u4 offset;
2919    u4 i;
2920
2921    pDexFile = meth->clazz->pDvmDex->pDexFile;
2922    pCode = dvmGetMethodCode(meth);
2923
2924    if (pCode->triesSize != 0) {
2925        handlersSize = dexGetHandlersSize(pCode);
2926        offset = dexGetFirstHandlerOffset(pCode);
2927    } else {
2928        handlersSize = 0;
2929        offset = 0;
2930    }
2931
2932    for (i = 0; i < handlersSize; i++) {
2933        DexCatchIterator iterator;
2934        dexCatchIteratorInit(&iterator, pCode, offset);
2935
2936        for (;;) {
2937            const DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
2938
2939            if (handler == NULL) {
2940                break;
2941            }
2942
2943            if (handler->address == (u4) insnIdx) {
2944                ClassObject* clazz;
2945
2946                if (handler->typeIdx == kDexNoIndex)
2947                    clazz = gDvm.exThrowable;
2948                else
2949                    clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx,
2950                                &localFailure);
2951
2952                if (clazz == NULL) {
2953                    LOG_VFY("VFY: unable to resolve exception class %u (%s)",
2954                        handler->typeIdx,
2955                        dexStringByTypeIdx(pDexFile, handler->typeIdx));
2956                    /* TODO: do we want to keep going?  If we don't fail
2957                     * this we run the risk of having a non-Throwable
2958                     * introduced at runtime.  However, that won't pass
2959                     * an instanceof test, so is essentially harmless. */
2960                } else {
2961                    if (commonSuper == NULL)
2962                        commonSuper = clazz;
2963                    else
2964                        commonSuper = findCommonSuperclass(clazz, commonSuper);
2965                }
2966            }
2967        }
2968
2969        offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
2970    }
2971
2972    if (commonSuper == NULL) {
2973        /* no catch blocks, or no catches with classes we can find */
2974        LOG_VFY_METH(meth,
2975            "VFY: unable to find exception handler at addr %#x", insnIdx);
2976        *pFailure = VERIFY_ERROR_GENERIC;
2977    } else {
2978        // TODO: verify the class is an instance of Throwable?
2979    }
2980
2981    return commonSuper;
2982}
2983
2984/*
2985 * Helper for initRegisterTable.
2986 *
2987 * Returns an updated copy of "storage".
2988 */
2989static u1* assignLineStorage(u1* storage, RegisterLine* line,
2990    bool trackMonitors, size_t regTypeSize, size_t monEntSize, size_t stackSize)
2991{
2992    line->regTypes = (RegType*) storage;
2993    storage += regTypeSize;
2994
2995    if (trackMonitors) {
2996        line->monitorEntries = (MonitorEntries*) storage;
2997        storage += monEntSize;
2998        line->monitorStack = (u4*) storage;
2999        storage += stackSize;
3000
3001        assert(line->monitorStackTop == 0);
3002    }
3003
3004    return storage;
3005}
3006
3007/*
3008 * Initialize the RegisterTable.
3009 *
3010 * Every instruction address can have a different set of information about
3011 * what's in which register, but for verification purposes we only need to
3012 * store it at branch target addresses (because we merge into that).
3013 *
3014 * By zeroing out the regType storage we are effectively initializing the
3015 * register information to kRegTypeUnknown.
3016 *
3017 * We jump through some hoops here to minimize the total number of
3018 * allocations we have to perform per method verified.
3019 */
3020static bool initRegisterTable(const VerifierData* vdata,
3021    RegisterTable* regTable, RegisterTrackingMode trackRegsFor)
3022{
3023    const Method* meth = vdata->method;
3024    const int insnsSize = vdata->insnsSize;
3025    const InsnFlags* insnFlags = vdata->insnFlags;
3026    const int kExtraLines = 2;  /* workLine, savedLine */
3027    int i;
3028
3029    /*
3030     * Every address gets a RegisterLine struct.  This is wasteful, but
3031     * not so much that it's worth chasing through an extra level of
3032     * indirection.
3033     */
3034    regTable->insnRegCountPlus = meth->registersSize + kExtraRegs;
3035    regTable->registerLines =
3036        (RegisterLine*) calloc(insnsSize, sizeof(RegisterLine));
3037    if (regTable->registerLines == NULL)
3038        return false;
3039
3040    assert(insnsSize > 0);
3041
3042    /*
3043     * Count up the number of "interesting" instructions.
3044     *
3045     * "All" means "every address that holds the start of an instruction".
3046     * "Branches" and "GcPoints" mean just those addresses.
3047     *
3048     * "GcPoints" fills about half the addresses, "Branches" about 15%.
3049     */
3050    int interestingCount = kExtraLines;
3051
3052    for (i = 0; i < insnsSize; i++) {
3053        bool interesting;
3054
3055        switch (trackRegsFor) {
3056        case kTrackRegsAll:
3057            interesting = dvmInsnIsOpcode(insnFlags, i);
3058            break;
3059        case kTrackRegsGcPoints:
3060            interesting = dvmInsnIsGcPoint(insnFlags, i) ||
3061                          dvmInsnIsBranchTarget(insnFlags, i);
3062            break;
3063        case kTrackRegsBranches:
3064            interesting = dvmInsnIsBranchTarget(insnFlags, i);
3065            break;
3066        default:
3067            dvmAbort();
3068            return false;
3069        }
3070
3071        if (interesting)
3072            interestingCount++;
3073
3074        /* count instructions, for display only */
3075        //if (dvmInsnIsOpcode(insnFlags, i))
3076        //    insnCount++;
3077    }
3078
3079    /*
3080     * Allocate storage for the register type arrays.
3081     * TODO: set trackMonitors based on global config option
3082     */
3083    size_t regTypeSize = regTable->insnRegCountPlus * sizeof(RegType);
3084    size_t monEntSize = regTable->insnRegCountPlus * sizeof(MonitorEntries);
3085    size_t stackSize = kMaxMonitorStackDepth * sizeof(u4);
3086    bool trackMonitors;
3087
3088    if (gDvm.monitorVerification) {
3089        trackMonitors = (vdata->monitorEnterCount != 0);
3090    } else {
3091        trackMonitors = false;
3092    }
3093
3094    size_t spacePerEntry = regTypeSize +
3095        (trackMonitors ? monEntSize + stackSize : 0);
3096    regTable->lineAlloc = calloc(interestingCount, spacePerEntry);
3097    if (regTable->lineAlloc == NULL)
3098        return false;
3099
3100#ifdef VERIFIER_STATS
3101    size_t totalSpace = interestingCount * spacePerEntry +
3102        insnsSize * sizeof(RegisterLine);
3103    if (gDvm.verifierStats.biggestAlloc < totalSpace)
3104        gDvm.verifierStats.biggestAlloc = totalSpace;
3105#endif
3106
3107    /*
3108     * Populate the sparse register line table.
3109     *
3110     * There is a RegisterLine associated with every address, but not
3111     * every RegisterLine has non-NULL pointers to storage for its fields.
3112     */
3113    u1* storage = (u1*)regTable->lineAlloc;
3114    for (i = 0; i < insnsSize; i++) {
3115        bool interesting;
3116
3117        switch (trackRegsFor) {
3118        case kTrackRegsAll:
3119            interesting = dvmInsnIsOpcode(insnFlags, i);
3120            break;
3121        case kTrackRegsGcPoints:
3122            interesting = dvmInsnIsGcPoint(insnFlags, i) ||
3123                          dvmInsnIsBranchTarget(insnFlags, i);
3124            break;
3125        case kTrackRegsBranches:
3126            interesting = dvmInsnIsBranchTarget(insnFlags, i);
3127            break;
3128        default:
3129            dvmAbort();
3130            return false;
3131        }
3132
3133        if (interesting) {
3134            storage = assignLineStorage(storage, &regTable->registerLines[i],
3135                trackMonitors, regTypeSize, monEntSize, stackSize);
3136        }
3137    }
3138
3139    /*
3140     * Grab storage for our "temporary" register lines.
3141     */
3142    storage = assignLineStorage(storage, &regTable->workLine,
3143        trackMonitors, regTypeSize, monEntSize, stackSize);
3144    storage = assignLineStorage(storage, &regTable->savedLine,
3145        trackMonitors, regTypeSize, monEntSize, stackSize);
3146
3147    //LOGD("Tracking registers for [%d], total %d in %d units",
3148    //    trackRegsFor, interestingCount-kExtraLines, insnsSize);
3149
3150    assert(storage - (u1*)regTable->lineAlloc ==
3151        (int) (interestingCount * spacePerEntry));
3152    assert(regTable->registerLines[0].regTypes != NULL);
3153    return true;
3154}
3155
3156/*
3157 * Free up any "hairy" structures associated with register lines.
3158 */
3159static void freeRegisterLineInnards(VerifierData* vdata)
3160{
3161    unsigned int idx;
3162
3163    if (vdata->registerLines == NULL)
3164        return;
3165
3166    for (idx = 0; idx < vdata->insnsSize; idx++) {
3167        BitVector* liveRegs = vdata->registerLines[idx].liveRegs;
3168        if (liveRegs != NULL)
3169            dvmFreeBitVector(liveRegs);
3170    }
3171}
3172
3173
3174/*
3175 * Verify that the arguments in a filled-new-array instruction are valid.
3176 *
3177 * "resClass" is the class refered to by pDecInsn->vB.
3178 */
3179static void verifyFilledNewArrayRegs(const Method* meth,
3180    RegisterLine* registerLine, const DecodedInstruction* pDecInsn,
3181    ClassObject* resClass, bool isRange, VerifyError* pFailure)
3182{
3183    u4 argCount = pDecInsn->vA;
3184    RegType expectedType;
3185    PrimitiveType elemType;
3186    unsigned int ui;
3187
3188    assert(dvmIsArrayClass(resClass));
3189    elemType = resClass->elementClass->primitiveType;
3190    if (elemType == PRIM_NOT) {
3191        expectedType = regTypeFromClass(resClass->elementClass);
3192    } else {
3193        expectedType = primitiveTypeToRegType(elemType);
3194    }
3195    //LOGI("filled-new-array: %s -> %d", resClass->descriptor, expectedType);
3196
3197    /*
3198     * Verify each register.  If "argCount" is bad, verifyRegisterType()
3199     * will run off the end of the list and fail.  It's legal, if silly,
3200     * for argCount to be zero.
3201     */
3202    for (ui = 0; ui < argCount; ui++) {
3203        u4 getReg;
3204
3205        if (isRange)
3206            getReg = pDecInsn->vC + ui;
3207        else
3208            getReg = pDecInsn->arg[ui];
3209
3210        verifyRegisterType(registerLine, getReg, expectedType, pFailure);
3211        if (!VERIFY_OK(*pFailure)) {
3212            LOG_VFY("VFY: filled-new-array arg %u(%u) not valid", ui, getReg);
3213            return;
3214        }
3215    }
3216}
3217
3218
3219/*
3220 * Replace an instruction with "throw-verification-error".  This allows us to
3221 * defer error reporting until the code path is first used.
3222 *
3223 * This is expected to be called during "just in time" verification, not
3224 * from within dexopt.  (Verification failures in dexopt will result in
3225 * postponement of verification to first use of the class.)
3226 *
3227 * The throw-verification-error instruction requires two code units.  Some
3228 * of the replaced instructions require three; the third code unit will
3229 * receive a "nop".  The instruction's length will be left unchanged
3230 * in "insnFlags".  If the erroring instruction is a jumbo instruction,
3231 * the throw-verification-error-jumbo instruction requires four code units.
3232 * Some jumbo instructions require five, and the fifth code unit will become
3233 * a "nop".
3234 *
3235 * The VM postpones setting of debugger breakpoints in unverified classes,
3236 * so there should be no clashes with the debugger.
3237 *
3238 * Returns "true" on success.
3239 */
3240static bool replaceFailingInstruction(const Method* meth, InsnFlags* insnFlags,
3241    int insnIdx, VerifyError failure)
3242{
3243    VerifyErrorRefType refType;
3244    u2* oldInsns = (u2*) meth->insns + insnIdx;
3245    int width;
3246    bool result = false;
3247
3248    if (gDvm.optimizing)
3249        LOGD("Weird: RFI during dexopt?");
3250
3251    /*
3252     * Generate the new instruction out of the old.
3253     *
3254     * First, make sure this is an instruction we're expecting to stomp on.
3255     */
3256    Opcode opcode = dexOpcodeFromCodeUnit(*oldInsns);
3257    switch (opcode) {
3258    case OP_CONST_CLASS:                // insn[1] == class ref, 2 bytes
3259    case OP_CHECK_CAST:
3260    case OP_INSTANCE_OF:
3261    case OP_NEW_INSTANCE:
3262    case OP_NEW_ARRAY:
3263    case OP_FILLED_NEW_ARRAY:           // insn[1] == class ref, 3 bytes
3264    case OP_FILLED_NEW_ARRAY_RANGE:
3265    case OP_CONST_CLASS_JUMBO:          // insn[1/2] == class ref, 4 bytes
3266    case OP_CHECK_CAST_JUMBO:
3267    case OP_NEW_INSTANCE_JUMBO:
3268    case OP_INSTANCE_OF_JUMBO:          // insn[1/2] == class ref, 5 bytes
3269    case OP_NEW_ARRAY_JUMBO:
3270    case OP_FILLED_NEW_ARRAY_JUMBO:
3271        refType = VERIFY_ERROR_REF_CLASS;
3272        break;
3273
3274    case OP_IGET:                       // insn[1] == field ref, 2 bytes
3275    case OP_IGET_BOOLEAN:
3276    case OP_IGET_BYTE:
3277    case OP_IGET_CHAR:
3278    case OP_IGET_SHORT:
3279    case OP_IGET_WIDE:
3280    case OP_IGET_OBJECT:
3281    case OP_IPUT:
3282    case OP_IPUT_BOOLEAN:
3283    case OP_IPUT_BYTE:
3284    case OP_IPUT_CHAR:
3285    case OP_IPUT_SHORT:
3286    case OP_IPUT_WIDE:
3287    case OP_IPUT_OBJECT:
3288    case OP_SGET:
3289    case OP_SGET_BOOLEAN:
3290    case OP_SGET_BYTE:
3291    case OP_SGET_CHAR:
3292    case OP_SGET_SHORT:
3293    case OP_SGET_WIDE:
3294    case OP_SGET_OBJECT:
3295    case OP_SPUT:
3296    case OP_SPUT_BOOLEAN:
3297    case OP_SPUT_BYTE:
3298    case OP_SPUT_CHAR:
3299    case OP_SPUT_SHORT:
3300    case OP_SPUT_WIDE:
3301    case OP_SPUT_OBJECT:
3302    case OP_SGET_JUMBO:                 // insn[1/2] == field ref, 4 bytes
3303    case OP_SGET_BOOLEAN_JUMBO:
3304    case OP_SGET_BYTE_JUMBO:
3305    case OP_SGET_CHAR_JUMBO:
3306    case OP_SGET_SHORT_JUMBO:
3307    case OP_SGET_WIDE_JUMBO:
3308    case OP_SGET_OBJECT_JUMBO:
3309    case OP_SPUT_JUMBO:
3310    case OP_SPUT_BOOLEAN_JUMBO:
3311    case OP_SPUT_BYTE_JUMBO:
3312    case OP_SPUT_CHAR_JUMBO:
3313    case OP_SPUT_SHORT_JUMBO:
3314    case OP_SPUT_WIDE_JUMBO:
3315    case OP_SPUT_OBJECT_JUMBO:
3316    case OP_IGET_JUMBO:                 // insn[1/2] == field ref, 5 bytes
3317    case OP_IGET_BOOLEAN_JUMBO:
3318    case OP_IGET_BYTE_JUMBO:
3319    case OP_IGET_CHAR_JUMBO:
3320    case OP_IGET_SHORT_JUMBO:
3321    case OP_IGET_WIDE_JUMBO:
3322    case OP_IGET_OBJECT_JUMBO:
3323    case OP_IPUT_JUMBO:
3324    case OP_IPUT_BOOLEAN_JUMBO:
3325    case OP_IPUT_BYTE_JUMBO:
3326    case OP_IPUT_CHAR_JUMBO:
3327    case OP_IPUT_SHORT_JUMBO:
3328    case OP_IPUT_WIDE_JUMBO:
3329    case OP_IPUT_OBJECT_JUMBO:
3330        refType = VERIFY_ERROR_REF_FIELD;
3331        break;
3332
3333    case OP_INVOKE_VIRTUAL:             // insn[1] == method ref, 3 bytes
3334    case OP_INVOKE_VIRTUAL_RANGE:
3335    case OP_INVOKE_SUPER:
3336    case OP_INVOKE_SUPER_RANGE:
3337    case OP_INVOKE_DIRECT:
3338    case OP_INVOKE_DIRECT_RANGE:
3339    case OP_INVOKE_STATIC:
3340    case OP_INVOKE_STATIC_RANGE:
3341    case OP_INVOKE_INTERFACE:
3342    case OP_INVOKE_INTERFACE_RANGE:
3343    case OP_INVOKE_VIRTUAL_JUMBO:       // insn[1/2] == method ref, 5 bytes
3344    case OP_INVOKE_SUPER_JUMBO:
3345    case OP_INVOKE_DIRECT_JUMBO:
3346    case OP_INVOKE_STATIC_JUMBO:
3347    case OP_INVOKE_INTERFACE_JUMBO:
3348        refType = VERIFY_ERROR_REF_METHOD;
3349        break;
3350
3351    default:
3352        /* could handle this in a generic way, but this is probably safer */
3353        LOG_VFY("GLITCH: verifier asked to replace opcode 0x%02x", opcode);
3354        goto bail;
3355    }
3356
3357    assert((dexGetFlagsFromOpcode(opcode) & kInstrCanThrow) != 0);
3358
3359    /* write a NOP over the third code unit, if necessary */
3360    width = dvmInsnGetWidth(insnFlags, insnIdx);
3361    switch (width) {
3362    case 2:
3363    case 4:
3364        /* nothing to do */
3365        break;
3366    case 3:
3367        dvmUpdateCodeUnit(meth, oldInsns+2, OP_NOP);
3368        break;
3369    case 5:
3370        dvmUpdateCodeUnit(meth, oldInsns+4, OP_NOP);
3371        break;
3372    default:
3373        /* whoops */
3374        LOGE("ERROR: stomped a %d-unit instruction with a verifier error",
3375            width);
3376        dvmAbort();
3377    }
3378
3379    /* check for jumbo opcodes */
3380    if (opcode > OP_DISPATCH_FF) {
3381        /* replace opcode and failure code */
3382        assert(width == 4 || width == 5);
3383        u2 newVal = (u2) ((OP_THROW_VERIFICATION_ERROR_JUMBO << 8) |
3384                           OP_DISPATCH_FF);
3385        dvmUpdateCodeUnit(meth, oldInsns, newVal);
3386        newVal = failure | (refType << kVerifyErrorRefTypeShift);
3387        dvmUpdateCodeUnit(meth, oldInsns+3, newVal);
3388    } else {
3389        /* encode the opcode, with the failure code in the high byte */
3390        assert(width == 2 || width == 3);
3391        u2 newVal = OP_THROW_VERIFICATION_ERROR |
3392            (failure << 8) | (refType << (8 + kVerifyErrorRefTypeShift));
3393        dvmUpdateCodeUnit(meth, oldInsns, newVal);
3394    }
3395
3396    result = true;
3397
3398bail:
3399    return result;
3400}
3401
3402/*
3403 * Handle a monitor-enter instruction.
3404 */
3405void handleMonitorEnter(RegisterLine* workLine, u4 regIdx, u4 insnIdx,
3406    VerifyError* pFailure)
3407{
3408    if (!regTypeIsReference(getRegisterType(workLine, regIdx))) {
3409        LOG_VFY("VFY: monitor-enter on non-object");
3410        *pFailure = VERIFY_ERROR_GENERIC;
3411        return;
3412    }
3413
3414    if (workLine->monitorEntries == NULL) {
3415        /* should only be true if monitor verification is disabled */
3416        assert(!gDvm.monitorVerification);
3417        return;
3418    }
3419
3420    if (workLine->monitorStackTop == kMaxMonitorStackDepth) {
3421        LOG_VFY("VFY: monitor-enter stack overflow (%d)",
3422            kMaxMonitorStackDepth);
3423        *pFailure = VERIFY_ERROR_GENERIC;
3424        return;
3425    }
3426
3427    /*
3428     * Push an entry on the stack, and set a bit in the register flags to
3429     * indicate that it's associated with this register.
3430     */
3431    workLine->monitorEntries[regIdx] |= 1 << workLine->monitorStackTop;
3432    workLine->monitorStack[workLine->monitorStackTop++] = insnIdx;
3433}
3434
3435/*
3436 * Handle a monitor-exit instruction.
3437 */
3438void handleMonitorExit(RegisterLine* workLine, u4 regIdx, u4 insnIdx,
3439    VerifyError* pFailure)
3440{
3441    if (!regTypeIsReference(getRegisterType(workLine, regIdx))) {
3442        LOG_VFY("VFY: monitor-exit on non-object");
3443        *pFailure = VERIFY_ERROR_GENERIC;
3444        return;
3445    }
3446
3447    if (workLine->monitorEntries == NULL) {
3448        /* should only be true if monitor verification is disabled */
3449        assert(!gDvm.monitorVerification);
3450        return;
3451    }
3452
3453    if (workLine->monitorStackTop == 0) {
3454        LOG_VFY("VFY: monitor-exit stack underflow");
3455        *pFailure = VERIFY_ERROR_GENERIC;
3456        return;
3457    }
3458
3459    /*
3460     * Confirm that the entry at the top of the stack is associated with
3461     * the register.  Pop the top entry off.
3462     */
3463    workLine->monitorStackTop--;
3464#ifdef BUG_3215458_FIXED
3465    /*
3466     * TODO: This code can safely be enabled if know we are working on
3467     * a dex file of format version 036 or later. (That is, we'll need to
3468     * add a check for the version number.)
3469     */
3470    if ((workLine->monitorEntries[regIdx] & (1 << workLine->monitorStackTop))
3471            == 0)
3472    {
3473        LOG_VFY("VFY: monitor-exit bit %d not set: addr=0x%04x (bits[%d]=%#x)",
3474            workLine->monitorStackTop, insnIdx, regIdx,
3475            workLine->monitorEntries[regIdx]);
3476        *pFailure = VERIFY_ERROR_GENERIC;
3477        return;
3478    }
3479#endif
3480    workLine->monitorStack[workLine->monitorStackTop] = 0;
3481
3482    /*
3483     * Clear the bit from the register flags.
3484     */
3485    workLine->monitorEntries[regIdx] &= ~(1 << workLine->monitorStackTop);
3486}
3487
3488
3489/*
3490 * ===========================================================================
3491 *      Entry point and driver loop
3492 * ===========================================================================
3493 */
3494
3495/*
3496 * One-time preparation.
3497 */
3498static void verifyPrep()
3499{
3500#ifndef NDEBUG
3501    /* only need to do this if the table was updated */
3502    checkMergeTab();
3503#endif
3504}
3505
3506/*
3507 * Entry point for the detailed code-flow analysis of a single method.
3508 */
3509bool dvmVerifyCodeFlow(VerifierData* vdata)
3510{
3511    bool result = false;
3512    const Method* meth = vdata->method;
3513    const int insnsSize = vdata->insnsSize;
3514    const bool generateRegisterMap = gDvm.generateRegisterMaps;
3515    RegisterTable regTable;
3516
3517    memset(&regTable, 0, sizeof(regTable));
3518
3519#ifdef VERIFIER_STATS
3520    gDvm.verifierStats.methodsExamined++;
3521    if (vdata->monitorEnterCount)
3522        gDvm.verifierStats.monEnterMethods++;
3523#endif
3524
3525    /* TODO: move this elsewhere -- we don't need to do this for every method */
3526    verifyPrep();
3527
3528    if (meth->registersSize * insnsSize > 4*1024*1024) {
3529        LOG_VFY_METH(meth,
3530            "VFY: warning: method is huge (regs=%d insnsSize=%d)",
3531            meth->registersSize, insnsSize);
3532        /* might be bogus data, might be some huge generated method */
3533    }
3534
3535    /*
3536     * Create register lists, and initialize them to "Unknown".  If we're
3537     * also going to create the register map, we need to retain the
3538     * register lists for a larger set of addresses.
3539     */
3540    if (!initRegisterTable(vdata, &regTable,
3541            generateRegisterMap ? kTrackRegsGcPoints : kTrackRegsBranches))
3542        goto bail;
3543
3544    vdata->registerLines = regTable.registerLines;
3545
3546    /*
3547     * Perform liveness analysis.
3548     *
3549     * We can do this before or after the main verifier pass.  The choice
3550     * affects whether or not we see the effects of verifier instruction
3551     * changes, i.e. substitution of throw-verification-error.
3552     *
3553     * In practice the ordering doesn't really matter, because T-V-E
3554     * just prunes "can continue", creating regions of dead code (with
3555     * corresponding register map data that will never be used).
3556     */
3557    if (generateRegisterMap &&
3558        gDvm.registerMapMode == kRegisterMapModeLivePrecise)
3559    {
3560        /*
3561         * Compute basic blocks and predecessor lists.
3562         */
3563        if (!dvmComputeVfyBasicBlocks(vdata))
3564            goto bail;
3565
3566        /*
3567         * Compute liveness.
3568         */
3569        if (!dvmComputeLiveness(vdata))
3570            goto bail;
3571    }
3572
3573    /*
3574     * Initialize the types of the registers that correspond to the
3575     * method arguments.  We can determine this from the method signature.
3576     */
3577    if (!setTypesFromSignature(meth, regTable.registerLines[0].regTypes,
3578            vdata->uninitMap))
3579        goto bail;
3580
3581    /*
3582     * Run the verifier.
3583     */
3584    if (!doCodeVerification(vdata, &regTable))
3585        goto bail;
3586
3587    /*
3588     * Generate a register map.
3589     */
3590    if (generateRegisterMap) {
3591        RegisterMap* pMap = dvmGenerateRegisterMapV(vdata);
3592        if (pMap != NULL) {
3593            /*
3594             * Tuck it into the Method struct.  It will either get used
3595             * directly or, if we're in dexopt, will be packed up and
3596             * appended to the DEX file.
3597             */
3598            dvmSetRegisterMap((Method*)meth, pMap);
3599        }
3600    }
3601
3602    /*
3603     * Success.
3604     */
3605    result = true;
3606
3607bail:
3608    freeRegisterLineInnards(vdata);
3609    free(regTable.registerLines);
3610    free(regTable.lineAlloc);
3611    return result;
3612}
3613
3614/*
3615 * Grind through the instructions.
3616 *
3617 * The basic strategy is as outlined in v3 4.11.1.2: set the "changed" bit
3618 * on the first instruction, process it (setting additional "changed" bits),
3619 * and repeat until there are no more.
3620 *
3621 * v3 4.11.1.1
3622 * - (N/A) operand stack is always the same size
3623 * - operand stack [registers] contain the correct types of values
3624 * - local variables [registers] contain the correct types of values
3625 * - methods are invoked with the appropriate arguments
3626 * - fields are assigned using values of appropriate types
3627 * - opcodes have the correct type values in operand registers
3628 * - there is never an uninitialized class instance in a local variable in
3629 *   code protected by an exception handler (operand stack is okay, because
3630 *   the operand stack is discarded when an exception is thrown) [can't
3631 *   know what's a local var w/o the debug info -- should fall out of
3632 *   register typing]
3633 *
3634 * v3 4.11.1.2
3635 * - execution cannot fall off the end of the code
3636 *
3637 * (We also do many of the items described in the "static checks" sections,
3638 * because it's easier to do them here.)
3639 *
3640 * We need an array of RegType values, one per register, for every
3641 * instruction.  If the method uses monitor-enter, we need extra data
3642 * for every register, and a stack for every "interesting" instruction.
3643 * In theory this could become quite large -- up to several megabytes for
3644 * a monster function.
3645 *
3646 * NOTE:
3647 * The spec forbids backward branches when there's an uninitialized reference
3648 * in a register.  The idea is to prevent something like this:
3649 *   loop:
3650 *     move r1, r0
3651 *     new-instance r0, MyClass
3652 *     ...
3653 *     if-eq rN, loop  // once
3654 *   initialize r0
3655 *
3656 * This leaves us with two different instances, both allocated by the
3657 * same instruction, but only one is initialized.  The scheme outlined in
3658 * v3 4.11.1.4 wouldn't catch this, so they work around it by preventing
3659 * backward branches.  We achieve identical results without restricting
3660 * code reordering by specifying that you can't execute the new-instance
3661 * instruction if a register contains an uninitialized instance created
3662 * by that same instrutcion.
3663 */
3664static bool doCodeVerification(VerifierData* vdata, RegisterTable* regTable)
3665{
3666    const Method* meth = vdata->method;
3667    InsnFlags* insnFlags = vdata->insnFlags;
3668    UninitInstanceMap* uninitMap = vdata->uninitMap;
3669    const int insnsSize = dvmGetMethodInsnsSize(meth);
3670    bool result = false;
3671    bool debugVerbose = false;
3672    int insnIdx, startGuess;
3673
3674    /*
3675     * Begin by marking the first instruction as "changed".
3676     */
3677    dvmInsnSetChanged(insnFlags, 0, true);
3678
3679    if (dvmWantVerboseVerification(meth)) {
3680        IF_LOGI() {
3681            char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3682            LOGI("Now verifying: %s.%s %s (ins=%d regs=%d)",
3683                meth->clazz->descriptor, meth->name, desc,
3684                meth->insSize, meth->registersSize);
3685            LOGI(" ------ [0    4    8    12   16   20   24   28   32   36");
3686            free(desc);
3687        }
3688        debugVerbose = true;
3689        gDebugVerbose = true;
3690    } else {
3691        gDebugVerbose = false;
3692    }
3693
3694    startGuess = 0;
3695
3696    /*
3697     * Continue until no instructions are marked "changed".
3698     */
3699    while (true) {
3700        /*
3701         * Find the first marked one.  Use "startGuess" as a way to find
3702         * one quickly.
3703         */
3704        for (insnIdx = startGuess; insnIdx < insnsSize; insnIdx++) {
3705            if (dvmInsnIsChanged(insnFlags, insnIdx))
3706                break;
3707        }
3708
3709        if (insnIdx == insnsSize) {
3710            if (startGuess != 0) {
3711                /* try again, starting from the top */
3712                startGuess = 0;
3713                continue;
3714            } else {
3715                /* all flags are clear */
3716                break;
3717            }
3718        }
3719
3720        /*
3721         * We carry the working set of registers from instruction to
3722         * instruction.  If this address can be the target of a branch
3723         * (or throw) instruction, or if we're skipping around chasing
3724         * "changed" flags, we need to load the set of registers from
3725         * the table.
3726         *
3727         * Because we always prefer to continue on to the next instruction,
3728         * we should never have a situation where we have a stray
3729         * "changed" flag set on an instruction that isn't a branch target.
3730         */
3731        if (dvmInsnIsBranchTarget(insnFlags, insnIdx)) {
3732            RegisterLine* workLine = &regTable->workLine;
3733
3734            copyLineFromTable(workLine, regTable, insnIdx);
3735        } else {
3736#ifndef NDEBUG
3737            /*
3738             * Sanity check: retrieve the stored register line (assuming
3739             * a full table) and make sure it actually matches.
3740             */
3741            RegisterLine* registerLine = getRegisterLine(regTable, insnIdx);
3742            if (registerLine->regTypes != NULL &&
3743                compareLineToTable(regTable, insnIdx, &regTable->workLine) != 0)
3744            {
3745                char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3746                LOG_VFY("HUH? workLine diverged in %s.%s %s",
3747                        meth->clazz->descriptor, meth->name, desc);
3748                free(desc);
3749                dumpRegTypes(vdata, registerLine, 0, "work",
3750                    uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS);
3751                dumpRegTypes(vdata, registerLine, 0, "insn",
3752                    uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS);
3753            }
3754#endif
3755        }
3756        if (debugVerbose) {
3757            dumpRegTypes(vdata, &regTable->workLine, insnIdx,
3758                NULL, uninitMap, SHOW_REG_DETAILS);
3759        }
3760
3761        //LOGI("process %s.%s %s %d",
3762        //    meth->clazz->descriptor, meth->name, meth->descriptor, insnIdx);
3763        if (!verifyInstruction(meth, insnFlags, regTable, insnIdx,
3764                uninitMap, &startGuess))
3765        {
3766            //LOGD("+++ %s bailing at %d", meth->name, insnIdx);
3767            goto bail;
3768        }
3769
3770        /*
3771         * Clear "changed" and mark as visited.
3772         */
3773        dvmInsnSetVisited(insnFlags, insnIdx, true);
3774        dvmInsnSetChanged(insnFlags, insnIdx, false);
3775    }
3776
3777    if (DEAD_CODE_SCAN && !IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
3778        /*
3779         * Scan for dead code.  There's nothing "evil" about dead code
3780         * (besides the wasted space), but it indicates a flaw somewhere
3781         * down the line, possibly in the verifier.
3782         *
3783         * If we've substituted "always throw" instructions into the stream,
3784         * we are almost certainly going to have some dead code.
3785         */
3786        int deadStart = -1;
3787        for (insnIdx = 0; insnIdx < insnsSize;
3788            insnIdx += dvmInsnGetWidth(insnFlags, insnIdx))
3789        {
3790            /*
3791             * Switch-statement data doesn't get "visited" by scanner.  It
3792             * may or may not be preceded by a padding NOP (for alignment).
3793             */
3794            int instr = meth->insns[insnIdx];
3795            if (instr == kPackedSwitchSignature ||
3796                instr == kSparseSwitchSignature ||
3797                instr == kArrayDataSignature ||
3798                (instr == OP_NOP &&
3799                 (meth->insns[insnIdx+1] == kPackedSwitchSignature ||
3800                  meth->insns[insnIdx+1] == kSparseSwitchSignature ||
3801                  meth->insns[insnIdx+1] == kArrayDataSignature)))
3802            {
3803                dvmInsnSetVisited(insnFlags, insnIdx, true);
3804            }
3805
3806            if (!dvmInsnIsVisited(insnFlags, insnIdx)) {
3807                if (deadStart < 0)
3808                    deadStart = insnIdx;
3809            } else if (deadStart >= 0) {
3810                IF_LOGD() {
3811                    char* desc =
3812                        dexProtoCopyMethodDescriptor(&meth->prototype);
3813                    LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s",
3814                        deadStart, insnIdx-1,
3815                        meth->clazz->descriptor, meth->name, desc);
3816                    free(desc);
3817                }
3818
3819                deadStart = -1;
3820            }
3821        }
3822        if (deadStart >= 0) {
3823            IF_LOGD() {
3824                char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3825                LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s",
3826                    deadStart, insnIdx-1,
3827                    meth->clazz->descriptor, meth->name, desc);
3828                free(desc);
3829            }
3830        }
3831    }
3832
3833    result = true;
3834
3835bail:
3836    return result;
3837}
3838
3839
3840/*
3841 * Perform verification for a single instruction.
3842 *
3843 * This requires fully decoding the instruction to determine the effect
3844 * it has on registers.
3845 *
3846 * Finds zero or more following instructions and sets the "changed" flag
3847 * if execution at that point needs to be (re-)evaluated.  Register changes
3848 * are merged into "regTypes" at the target addresses.  Does not set or
3849 * clear any other flags in "insnFlags".
3850 *
3851 * This may alter meth->insns if we need to replace an instruction with
3852 * throw-verification-error.
3853 */
3854static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,
3855    RegisterTable* regTable, int insnIdx, UninitInstanceMap* uninitMap,
3856    int* pStartGuess)
3857{
3858    const int insnsSize = dvmGetMethodInsnsSize(meth);
3859    const u2* insns = meth->insns + insnIdx;
3860    bool result = false;
3861
3862#ifdef VERIFIER_STATS
3863    if (dvmInsnIsVisited(insnFlags, insnIdx)) {
3864        gDvm.verifierStats.instrsReexamined++;
3865    } else {
3866        gDvm.verifierStats.instrsExamined++;
3867    }
3868#endif
3869
3870    /*
3871     * Once we finish decoding the instruction, we need to figure out where
3872     * we can go from here.  There are three possible ways to transfer
3873     * control to another statement:
3874     *
3875     * (1) Continue to the next instruction.  Applies to all but
3876     *     unconditional branches, method returns, and exception throws.
3877     * (2) Branch to one or more possible locations.  Applies to branches
3878     *     and switch statements.
3879     * (3) Exception handlers.  Applies to any instruction that can
3880     *     throw an exception that is handled by an encompassing "try"
3881     *     block.
3882     *
3883     * We can also return, in which case there is no successor instruction
3884     * from this point.
3885     *
3886     * The behavior can be determined from the OpcodeFlags.
3887     */
3888
3889    RegisterLine* workLine = &regTable->workLine;
3890    const DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
3891    ClassObject* resClass;
3892    s4 branchTarget = 0;
3893    const int insnRegCount = meth->registersSize;
3894    RegType tmpType;
3895    DecodedInstruction decInsn;
3896    bool justSetResult = false;
3897    VerifyError failure = VERIFY_ERROR_NONE;
3898
3899#ifndef NDEBUG
3900    memset(&decInsn, 0x81, sizeof(decInsn));
3901#endif
3902    dexDecodeInstruction(insns, &decInsn);
3903
3904    int nextFlags = dexGetFlagsFromOpcode(decInsn.opcode);
3905
3906    /*
3907     * Make a copy of the previous register state.  If the instruction
3908     * can throw an exception, we will copy/merge this into the "catch"
3909     * address rather than workLine, because we don't want the result
3910     * from the "successful" code path (e.g. a check-cast that "improves"
3911     * a type) to be visible to the exception handler.
3912     */
3913    if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
3914    {
3915        copyRegisterLine(&regTable->savedLine, workLine,
3916            regTable->insnRegCountPlus);
3917    } else {
3918#ifndef NDEBUG
3919        memset(regTable->savedLine.regTypes, 0xdd,
3920            regTable->insnRegCountPlus * sizeof(RegType));
3921#endif
3922    }
3923
3924    switch (decInsn.opcode) {
3925    case OP_NOP:
3926        /*
3927         * A "pure" NOP has no effect on anything.  Data tables start with
3928         * a signature that looks like a NOP; if we see one of these in
3929         * the course of executing code then we have a problem.
3930         */
3931        if (decInsn.vA != 0) {
3932            LOG_VFY("VFY: encountered data table in instruction stream");
3933            failure = VERIFY_ERROR_GENERIC;
3934        }
3935        break;
3936
3937    case OP_MOVE:
3938    case OP_MOVE_FROM16:
3939    case OP_MOVE_16:
3940        copyRegister1(workLine, decInsn.vA, decInsn.vB, kTypeCategory1nr,
3941            &failure);
3942        break;
3943    case OP_MOVE_WIDE:
3944    case OP_MOVE_WIDE_FROM16:
3945    case OP_MOVE_WIDE_16:
3946        copyRegister2(workLine, decInsn.vA, decInsn.vB, &failure);
3947        break;
3948    case OP_MOVE_OBJECT:
3949    case OP_MOVE_OBJECT_FROM16:
3950    case OP_MOVE_OBJECT_16:
3951        copyRegister1(workLine, decInsn.vA, decInsn.vB, kTypeCategoryRef,
3952            &failure);
3953        break;
3954
3955    /*
3956     * The move-result instructions copy data out of a "pseudo-register"
3957     * with the results from the last method invocation.  In practice we
3958     * might want to hold the result in an actual CPU register, so the
3959     * Dalvik spec requires that these only appear immediately after an
3960     * invoke or filled-new-array.
3961     *
3962     * These calls invalidate the "result" register.  (This is now
3963     * redundant with the reset done below, but it can make the debug info
3964     * easier to read in some cases.)
3965     */
3966    case OP_MOVE_RESULT:
3967        copyResultRegister1(workLine, insnRegCount, decInsn.vA,
3968            kTypeCategory1nr, &failure);
3969        break;
3970    case OP_MOVE_RESULT_WIDE:
3971        copyResultRegister2(workLine, insnRegCount, decInsn.vA, &failure);
3972        break;
3973    case OP_MOVE_RESULT_OBJECT:
3974        copyResultRegister1(workLine, insnRegCount, decInsn.vA,
3975            kTypeCategoryRef, &failure);
3976        break;
3977
3978    case OP_MOVE_EXCEPTION:
3979        /*
3980         * This statement can only appear as the first instruction in an
3981         * exception handler (though not all exception handlers need to
3982         * have one of these).  We verify that as part of extracting the
3983         * exception type from the catch block list.
3984         *
3985         * "resClass" will hold the closest common superclass of all
3986         * exceptions that can be handled here.
3987         */
3988        resClass = getCaughtExceptionType(meth, insnIdx, &failure);
3989        if (resClass == NULL) {
3990            assert(!VERIFY_OK(failure));
3991        } else {
3992            setRegisterType(workLine, decInsn.vA, regTypeFromClass(resClass));
3993        }
3994        break;
3995
3996    case OP_RETURN_VOID:
3997        if (!checkConstructorReturn(meth, workLine, insnRegCount)) {
3998            failure = VERIFY_ERROR_GENERIC;
3999        } else if (getMethodReturnType(meth) != kRegTypeUnknown) {
4000            LOG_VFY("VFY: return-void not expected");
4001            failure = VERIFY_ERROR_GENERIC;
4002        }
4003        break;
4004    case OP_RETURN:
4005        if (!checkConstructorReturn(meth, workLine, insnRegCount)) {
4006            failure = VERIFY_ERROR_GENERIC;
4007        } else {
4008            /* check the method signature */
4009            RegType returnType = getMethodReturnType(meth);
4010            checkTypeCategory(returnType, kTypeCategory1nr, &failure);
4011            if (!VERIFY_OK(failure))
4012                LOG_VFY("VFY: return-1nr not expected");
4013
4014            /*
4015             * javac generates synthetic functions that write byte values
4016             * into boolean fields. Also, it may use integer values for
4017             * boolean, byte, short, and character return types.
4018             */
4019            RegType srcType = getRegisterType(workLine, decInsn.vA);
4020            if ((returnType == kRegTypeBoolean && srcType == kRegTypeByte) ||
4021                ((returnType == kRegTypeBoolean || returnType == kRegTypeByte ||
4022                  returnType == kRegTypeShort || returnType == kRegTypeChar) &&
4023                 srcType == kRegTypeInteger))
4024                returnType = srcType;
4025
4026            /* check the register contents */
4027            verifyRegisterType(workLine, decInsn.vA, returnType, &failure);
4028            if (!VERIFY_OK(failure)) {
4029                LOG_VFY("VFY: return-1nr on invalid register v%d",
4030                    decInsn.vA);
4031            }
4032        }
4033        break;
4034    case OP_RETURN_WIDE:
4035        if (!checkConstructorReturn(meth, workLine, insnRegCount)) {
4036            failure = VERIFY_ERROR_GENERIC;
4037        } else {
4038            RegType returnType;
4039
4040            /* check the method signature */
4041            returnType = getMethodReturnType(meth);
4042            checkTypeCategory(returnType, kTypeCategory2, &failure);
4043            if (!VERIFY_OK(failure))
4044                LOG_VFY("VFY: return-wide not expected");
4045
4046            /* check the register contents */
4047            verifyRegisterType(workLine, decInsn.vA, returnType, &failure);
4048            if (!VERIFY_OK(failure)) {
4049                LOG_VFY("VFY: return-wide on invalid register pair v%d",
4050                    decInsn.vA);
4051            }
4052        }
4053        break;
4054    case OP_RETURN_OBJECT:
4055        if (!checkConstructorReturn(meth, workLine, insnRegCount)) {
4056            failure = VERIFY_ERROR_GENERIC;
4057        } else {
4058            RegType returnType = getMethodReturnType(meth);
4059            checkTypeCategory(returnType, kTypeCategoryRef, &failure);
4060            if (!VERIFY_OK(failure)) {
4061                LOG_VFY("VFY: return-object not expected");
4062                break;
4063            }
4064
4065            /* returnType is the *expected* return type, not register value */
4066            assert(returnType != kRegTypeZero);
4067            assert(!regTypeIsUninitReference(returnType));
4068
4069            /*
4070             * Verify that the reference in vAA is an instance of the type
4071             * in "returnType".  The Zero type is allowed here.  If the
4072             * method is declared to return an interface, then any
4073             * initialized reference is acceptable.
4074             *
4075             * Note getClassFromRegister fails if the register holds an
4076             * uninitialized reference, so we do not allow them to be
4077             * returned.
4078             */
4079            ClassObject* declClass;
4080
4081            declClass = regTypeInitializedReferenceToClass(returnType);
4082            resClass = getClassFromRegister(workLine, decInsn.vA, &failure);
4083            if (!VERIFY_OK(failure))
4084                break;
4085            if (resClass != NULL) {
4086                if (!dvmIsInterfaceClass(declClass) &&
4087                    !dvmInstanceof(resClass, declClass))
4088                {
4089                    LOG_VFY("VFY: returning %s (cl=%p), declared %s (cl=%p)",
4090                            resClass->descriptor, resClass->classLoader,
4091                            declClass->descriptor, declClass->classLoader);
4092                    failure = VERIFY_ERROR_GENERIC;
4093                    break;
4094                }
4095            }
4096        }
4097        break;
4098
4099    case OP_CONST_4:
4100    case OP_CONST_16:
4101    case OP_CONST:
4102        /* could be boolean, int, float, or a null reference */
4103        setRegisterType(workLine, decInsn.vA,
4104            determineCat1Const((s4)decInsn.vB));
4105        break;
4106    case OP_CONST_HIGH16:
4107        /* could be boolean, int, float, or a null reference */
4108        setRegisterType(workLine, decInsn.vA,
4109            determineCat1Const((s4) decInsn.vB << 16));
4110        break;
4111    case OP_CONST_WIDE_16:
4112    case OP_CONST_WIDE_32:
4113    case OP_CONST_WIDE:
4114    case OP_CONST_WIDE_HIGH16:
4115        /* could be long or double; resolved upon use */
4116        setRegisterType(workLine, decInsn.vA, kRegTypeConstLo);
4117        break;
4118    case OP_CONST_STRING:
4119    case OP_CONST_STRING_JUMBO:
4120        assert(gDvm.classJavaLangString != NULL);
4121        setRegisterType(workLine, decInsn.vA,
4122            regTypeFromClass(gDvm.classJavaLangString));
4123        break;
4124    case OP_CONST_CLASS:
4125    case OP_CONST_CLASS_JUMBO:
4126        assert(gDvm.classJavaLangClass != NULL);
4127        /* make sure we can resolve the class; access check is important */
4128        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
4129        if (resClass == NULL) {
4130            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
4131            dvmLogUnableToResolveClass(badClassDesc, meth);
4132            LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s",
4133                decInsn.vB, badClassDesc, meth->clazz->descriptor);
4134            assert(failure != VERIFY_ERROR_GENERIC);
4135        } else {
4136            setRegisterType(workLine, decInsn.vA,
4137                regTypeFromClass(gDvm.classJavaLangClass));
4138        }
4139        break;
4140
4141    case OP_MONITOR_ENTER:
4142        handleMonitorEnter(workLine, decInsn.vA, insnIdx, &failure);
4143        break;
4144    case OP_MONITOR_EXIT:
4145        /*
4146         * monitor-exit instructions are odd.  They can throw exceptions,
4147         * but when they do they act as if they succeeded and the PC is
4148         * pointing to the following instruction.  (This behavior goes back
4149         * to the need to handle asynchronous exceptions, a now-deprecated
4150         * feature that Dalvik doesn't support.)
4151         *
4152         * In practice we don't need to worry about this.  The only
4153         * exceptions that can be thrown from monitor-exit are for a
4154         * null reference and -exit without a matching -enter.  If the
4155         * structured locking checks are working, the former would have
4156         * failed on the -enter instruction, and the latter is impossible.
4157         *
4158         * This is fortunate, because issue 3221411 prevents us from
4159         * chasing the "can throw" path when monitor verification is
4160         * enabled.  If we can fully verify the locking we can ignore
4161         * some catch blocks (which will show up as "dead" code when
4162         * we skip them here); if we can't, then the code path could be
4163         * "live" so we still need to check it.
4164         */
4165        if (workLine->monitorEntries != NULL)
4166            nextFlags &= ~kInstrCanThrow;
4167        handleMonitorExit(workLine, decInsn.vA, insnIdx, &failure);
4168        break;
4169
4170    case OP_CHECK_CAST:
4171    case OP_CHECK_CAST_JUMBO:
4172        /*
4173         * If this instruction succeeds, we will promote register vA to
4174         * the type in vB.  (This could be a demotion -- not expected, so
4175         * we don't try to address it.)
4176         *
4177         * If it fails, an exception is thrown, which we deal with later
4178         * by ignoring the update to decInsn.vA when branching to a handler.
4179         */
4180        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
4181        if (resClass == NULL) {
4182            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
4183            dvmLogUnableToResolveClass(badClassDesc, meth);
4184            LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s",
4185                decInsn.vB, badClassDesc, meth->clazz->descriptor);
4186            assert(failure != VERIFY_ERROR_GENERIC);
4187        } else {
4188            RegType origType;
4189
4190            origType = getRegisterType(workLine, decInsn.vA);
4191            if (!regTypeIsReference(origType)) {
4192                LOG_VFY("VFY: check-cast on non-reference in v%u",decInsn.vA);
4193                failure = VERIFY_ERROR_GENERIC;
4194                break;
4195            }
4196            setRegisterType(workLine, decInsn.vA, regTypeFromClass(resClass));
4197        }
4198        break;
4199    case OP_INSTANCE_OF:
4200    case OP_INSTANCE_OF_JUMBO:
4201        /* make sure we're checking a reference type */
4202        tmpType = getRegisterType(workLine, decInsn.vB);
4203        if (!regTypeIsReference(tmpType)) {
4204            LOG_VFY("VFY: vB not a reference (%d)", tmpType);
4205            failure = VERIFY_ERROR_GENERIC;
4206            break;
4207        }
4208
4209        /* make sure we can resolve the class; access check is important */
4210        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
4211        if (resClass == NULL) {
4212            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
4213            dvmLogUnableToResolveClass(badClassDesc, meth);
4214            LOG_VFY("VFY: unable to resolve instanceof %d (%s) in %s",
4215                decInsn.vC, badClassDesc, meth->clazz->descriptor);
4216            assert(failure != VERIFY_ERROR_GENERIC);
4217        } else {
4218            /* result is boolean */
4219            setRegisterType(workLine, decInsn.vA, kRegTypeBoolean);
4220        }
4221        break;
4222
4223    case OP_ARRAY_LENGTH:
4224        resClass = getClassFromRegister(workLine, decInsn.vB, &failure);
4225        if (!VERIFY_OK(failure))
4226            break;
4227        if (resClass != NULL && !dvmIsArrayClass(resClass)) {
4228            LOG_VFY("VFY: array-length on non-array");
4229            failure = VERIFY_ERROR_GENERIC;
4230            break;
4231        }
4232        setRegisterType(workLine, decInsn.vA, kRegTypeInteger);
4233        break;
4234
4235    case OP_NEW_INSTANCE:
4236    case OP_NEW_INSTANCE_JUMBO:
4237        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
4238        if (resClass == NULL) {
4239            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
4240            dvmLogUnableToResolveClass(badClassDesc, meth);
4241            LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s",
4242                decInsn.vB, badClassDesc, meth->clazz->descriptor);
4243            assert(failure != VERIFY_ERROR_GENERIC);
4244        } else {
4245            RegType uninitType;
4246
4247            /* can't create an instance of an interface or abstract class */
4248            if (dvmIsAbstractClass(resClass) || dvmIsInterfaceClass(resClass)) {
4249                LOG_VFY("VFY: new-instance on interface or abstract class %s",
4250                    resClass->descriptor);
4251                failure = VERIFY_ERROR_INSTANTIATION;
4252                break;
4253            }
4254
4255            /* add resolved class to uninit map if not already there */
4256            int uidx = setUninitInstance(uninitMap, insnIdx, resClass);
4257            assert(uidx >= 0);
4258            uninitType = regTypeFromUninitIndex(uidx);
4259
4260            /*
4261             * Any registers holding previous allocations from this address
4262             * that have not yet been initialized must be marked invalid.
4263             */
4264            markUninitRefsAsInvalid(workLine, insnRegCount, uninitMap,
4265                uninitType);
4266
4267            /* add the new uninitialized reference to the register ste */
4268            setRegisterType(workLine, decInsn.vA, uninitType);
4269        }
4270        break;
4271    case OP_NEW_ARRAY:
4272    case OP_NEW_ARRAY_JUMBO:
4273        resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
4274        if (resClass == NULL) {
4275            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
4276            dvmLogUnableToResolveClass(badClassDesc, meth);
4277            LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s",
4278                decInsn.vC, badClassDesc, meth->clazz->descriptor);
4279            assert(failure != VERIFY_ERROR_GENERIC);
4280        } else if (!dvmIsArrayClass(resClass)) {
4281            LOG_VFY("VFY: new-array on non-array class");
4282            failure = VERIFY_ERROR_GENERIC;
4283        } else {
4284            /* make sure "size" register is valid type */
4285            verifyRegisterType(workLine, decInsn.vB, kRegTypeInteger, &failure);
4286            /* set register type to array class */
4287            setRegisterType(workLine, decInsn.vA, regTypeFromClass(resClass));
4288        }
4289        break;
4290    case OP_FILLED_NEW_ARRAY:
4291    case OP_FILLED_NEW_ARRAY_RANGE:
4292    case OP_FILLED_NEW_ARRAY_JUMBO:
4293        resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
4294        if (resClass == NULL) {
4295            const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
4296            dvmLogUnableToResolveClass(badClassDesc, meth);
4297            LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s",
4298                decInsn.vB, badClassDesc, meth->clazz->descriptor);
4299            assert(failure != VERIFY_ERROR_GENERIC);
4300        } else if (!dvmIsArrayClass(resClass)) {
4301            LOG_VFY("VFY: filled-new-array on non-array class");
4302            failure = VERIFY_ERROR_GENERIC;
4303        } else {
4304            bool isRange = (decInsn.opcode == OP_FILLED_NEW_ARRAY_RANGE ||
4305                            decInsn.opcode == OP_FILLED_NEW_ARRAY_JUMBO);
4306
4307            /* check the arguments to the instruction */
4308            verifyFilledNewArrayRegs(meth, workLine, &decInsn,
4309                resClass, isRange, &failure);
4310            /* filled-array result goes into "result" register */
4311            setResultRegisterType(workLine, insnRegCount,
4312                regTypeFromClass(resClass));
4313            justSetResult = true;
4314        }
4315        break;
4316
4317    case OP_CMPL_FLOAT:
4318    case OP_CMPG_FLOAT:
4319        verifyRegisterType(workLine, decInsn.vB, kRegTypeFloat, &failure);
4320        verifyRegisterType(workLine, decInsn.vC, kRegTypeFloat, &failure);
4321        setRegisterType(workLine, decInsn.vA, kRegTypeBoolean);
4322        break;
4323    case OP_CMPL_DOUBLE:
4324    case OP_CMPG_DOUBLE:
4325        verifyRegisterType(workLine, decInsn.vB, kRegTypeDoubleLo, &failure);
4326        verifyRegisterType(workLine, decInsn.vC, kRegTypeDoubleLo, &failure);
4327        setRegisterType(workLine, decInsn.vA, kRegTypeBoolean);
4328        break;
4329    case OP_CMP_LONG:
4330        verifyRegisterType(workLine, decInsn.vB, kRegTypeLongLo, &failure);
4331        verifyRegisterType(workLine, decInsn.vC, kRegTypeLongLo, &failure);
4332        setRegisterType(workLine, decInsn.vA, kRegTypeBoolean);
4333        break;
4334
4335    case OP_THROW:
4336        resClass = getClassFromRegister(workLine, decInsn.vA, &failure);
4337        if (VERIFY_OK(failure) && resClass != NULL) {
4338            if (!dvmInstanceof(resClass, gDvm.exThrowable)) {
4339                LOG_VFY("VFY: thrown class %s not instanceof Throwable",
4340                        resClass->descriptor);
4341                failure = VERIFY_ERROR_GENERIC;
4342            }
4343        }
4344        break;
4345
4346    case OP_GOTO:
4347    case OP_GOTO_16:
4348    case OP_GOTO_32:
4349        /* no effect on or use of registers */
4350        break;
4351
4352    case OP_PACKED_SWITCH:
4353    case OP_SPARSE_SWITCH:
4354        /* verify that vAA is an integer, or can be converted to one */
4355        verifyRegisterType(workLine, decInsn.vA, kRegTypeInteger, &failure);
4356        break;
4357
4358    case OP_FILL_ARRAY_DATA:
4359        {
4360            RegType valueType;
4361            const u2 *arrayData;
4362            u2 elemWidth;
4363
4364            /* Similar to the verification done for APUT */
4365            resClass = getClassFromRegister(workLine, decInsn.vA, &failure);
4366            if (!VERIFY_OK(failure))
4367                break;
4368
4369            /* resClass can be null if the reg type is Zero */
4370            if (resClass == NULL)
4371                break;
4372
4373            if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4374                resClass->elementClass->primitiveType == PRIM_NOT ||
4375                resClass->elementClass->primitiveType == PRIM_VOID)
4376            {
4377                LOG_VFY("VFY: invalid fill-array-data on %s",
4378                        resClass->descriptor);
4379                failure = VERIFY_ERROR_GENERIC;
4380                break;
4381            }
4382
4383            valueType = primitiveTypeToRegType(
4384                                    resClass->elementClass->primitiveType);
4385            assert(valueType != kRegTypeUnknown);
4386
4387            /*
4388             * Now verify if the element width in the table matches the element
4389             * width declared in the array
4390             */
4391            arrayData = insns + (insns[1] | (((s4)insns[2]) << 16));
4392            if (arrayData[0] != kArrayDataSignature) {
4393                LOG_VFY("VFY: invalid magic for array-data");
4394                failure = VERIFY_ERROR_GENERIC;
4395                break;
4396            }
4397
4398            switch (resClass->elementClass->primitiveType) {
4399                case PRIM_BOOLEAN:
4400                case PRIM_BYTE:
4401                     elemWidth = 1;
4402                     break;
4403                case PRIM_CHAR:
4404                case PRIM_SHORT:
4405                     elemWidth = 2;
4406                     break;
4407                case PRIM_FLOAT:
4408                case PRIM_INT:
4409                     elemWidth = 4;
4410                     break;
4411                case PRIM_DOUBLE:
4412                case PRIM_LONG:
4413                     elemWidth = 8;
4414                     break;
4415                default:
4416                     elemWidth = 0;
4417                     break;
4418            }
4419
4420            /*
4421             * Since we don't compress the data in Dex, expect to see equal
4422             * width of data stored in the table and expected from the array
4423             * class.
4424             */
4425            if (arrayData[1] != elemWidth) {
4426                LOG_VFY("VFY: array-data size mismatch (%d vs %d)",
4427                        arrayData[1], elemWidth);
4428                failure = VERIFY_ERROR_GENERIC;
4429            }
4430        }
4431        break;
4432
4433    case OP_IF_EQ:
4434    case OP_IF_NE:
4435        {
4436            RegType type1, type2;
4437
4438            type1 = getRegisterType(workLine, decInsn.vA);
4439            type2 = getRegisterType(workLine, decInsn.vB);
4440
4441            /* both references? */
4442            if (regTypeIsReference(type1) && regTypeIsReference(type2))
4443                break;
4444
4445            /* both category-1nr? */
4446            checkTypeCategory(type1, kTypeCategory1nr, &failure);
4447            checkTypeCategory(type2, kTypeCategory1nr, &failure);
4448            if (!VERIFY_OK(failure)) {
4449                LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1");
4450                break;
4451            }
4452        }
4453        break;
4454    case OP_IF_LT:
4455    case OP_IF_GE:
4456    case OP_IF_GT:
4457    case OP_IF_LE:
4458        tmpType = getRegisterType(workLine, decInsn.vA);
4459        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4460        if (!VERIFY_OK(failure)) {
4461            LOG_VFY("VFY: args to 'if' must be cat-1nr");
4462            break;
4463        }
4464        tmpType = getRegisterType(workLine, decInsn.vB);
4465        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4466        if (!VERIFY_OK(failure)) {
4467            LOG_VFY("VFY: args to 'if' must be cat-1nr");
4468            break;
4469        }
4470        break;
4471    case OP_IF_EQZ:
4472    case OP_IF_NEZ:
4473        tmpType = getRegisterType(workLine, decInsn.vA);
4474        if (regTypeIsReference(tmpType))
4475            break;
4476        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4477        if (!VERIFY_OK(failure))
4478            LOG_VFY("VFY: expected cat-1 arg to if");
4479        break;
4480    case OP_IF_LTZ:
4481    case OP_IF_GEZ:
4482    case OP_IF_GTZ:
4483    case OP_IF_LEZ:
4484        tmpType = getRegisterType(workLine, decInsn.vA);
4485        checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4486        if (!VERIFY_OK(failure))
4487            LOG_VFY("VFY: expected cat-1 arg to if");
4488        break;
4489
4490    case OP_AGET:
4491        tmpType = kRegTypeConstInteger;
4492        goto aget_1nr_common;
4493    case OP_AGET_BOOLEAN:
4494        tmpType = kRegTypeBoolean;
4495        goto aget_1nr_common;
4496    case OP_AGET_BYTE:
4497        tmpType = kRegTypeByte;
4498        goto aget_1nr_common;
4499    case OP_AGET_CHAR:
4500        tmpType = kRegTypeChar;
4501        goto aget_1nr_common;
4502    case OP_AGET_SHORT:
4503        tmpType = kRegTypeShort;
4504        goto aget_1nr_common;
4505aget_1nr_common:
4506        {
4507            RegType srcType, indexType;
4508
4509            indexType = getRegisterType(workLine, decInsn.vC);
4510            checkArrayIndexType(meth, indexType, &failure);
4511            if (!VERIFY_OK(failure))
4512                break;
4513
4514            resClass = getClassFromRegister(workLine, decInsn.vB, &failure);
4515            if (!VERIFY_OK(failure))
4516                break;
4517            if (resClass != NULL) {
4518                /* verify the class */
4519                if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4520                    resClass->elementClass->primitiveType == PRIM_NOT)
4521                {
4522                    LOG_VFY("VFY: invalid aget-1nr target %s",
4523                        resClass->descriptor);
4524                    failure = VERIFY_ERROR_GENERIC;
4525                    break;
4526                }
4527
4528                /* make sure array type matches instruction */
4529                srcType = primitiveTypeToRegType(
4530                                        resClass->elementClass->primitiveType);
4531
4532                /* differentiate between float and int */
4533                if (srcType == kRegTypeFloat || srcType == kRegTypeInteger)
4534                    tmpType = srcType;
4535
4536                if (!checkFieldArrayStore1nr(tmpType, srcType)) {
4537                    LOG_VFY("VFY: invalid aget-1nr, array type=%d with"
4538                            " inst type=%d (on %s)",
4539                        srcType, tmpType, resClass->descriptor);
4540                    failure = VERIFY_ERROR_GENERIC;
4541                    break;
4542                }
4543
4544            }
4545            setRegisterType(workLine, decInsn.vA, tmpType);
4546        }
4547        break;
4548
4549    case OP_AGET_WIDE:
4550        {
4551            RegType dstType, indexType;
4552
4553            indexType = getRegisterType(workLine, decInsn.vC);
4554            checkArrayIndexType(meth, indexType, &failure);
4555            if (!VERIFY_OK(failure))
4556                break;
4557
4558            resClass = getClassFromRegister(workLine, decInsn.vB, &failure);
4559            if (!VERIFY_OK(failure))
4560                break;
4561            if (resClass != NULL) {
4562                /* verify the class */
4563                if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4564                    resClass->elementClass->primitiveType == PRIM_NOT)
4565                {
4566                    LOG_VFY("VFY: invalid aget-wide target %s",
4567                        resClass->descriptor);
4568                    failure = VERIFY_ERROR_GENERIC;
4569                    break;
4570                }
4571
4572                /* try to refine "dstType" */
4573                switch (resClass->elementClass->primitiveType) {
4574                case PRIM_LONG:
4575                    dstType = kRegTypeLongLo;
4576                    break;
4577                case PRIM_DOUBLE:
4578                    dstType = kRegTypeDoubleLo;
4579                    break;
4580                default:
4581                    LOG_VFY("VFY: invalid aget-wide on %s",
4582                        resClass->descriptor);
4583                    dstType = kRegTypeUnknown;
4584                    failure = VERIFY_ERROR_GENERIC;
4585                    break;
4586                }
4587            } else {
4588                /*
4589                 * Null array ref; this code path will fail at runtime.  We
4590                 * know this is either long or double, so label it const.
4591                 */
4592                dstType = kRegTypeConstLo;
4593            }
4594            setRegisterType(workLine, decInsn.vA, dstType);
4595        }
4596        break;
4597
4598    case OP_AGET_OBJECT:
4599        {
4600            RegType dstType, indexType;
4601
4602            indexType = getRegisterType(workLine, decInsn.vC);
4603            checkArrayIndexType(meth, indexType, &failure);
4604            if (!VERIFY_OK(failure))
4605                break;
4606
4607            /* get the class of the array we're pulling an object from */
4608            resClass = getClassFromRegister(workLine, decInsn.vB, &failure);
4609            if (!VERIFY_OK(failure))
4610                break;
4611            if (resClass != NULL) {
4612                ClassObject* elementClass;
4613
4614                assert(resClass != NULL);
4615                if (!dvmIsArrayClass(resClass)) {
4616                    LOG_VFY("VFY: aget-object on non-array class");
4617                    failure = VERIFY_ERROR_GENERIC;
4618                    break;
4619                }
4620                assert(resClass->elementClass != NULL);
4621
4622                /*
4623                 * Find the element class.  resClass->elementClass indicates
4624                 * the basic type, which won't be what we want for a
4625                 * multi-dimensional array.
4626                 */
4627                if (resClass->descriptor[1] == '[') {
4628                    assert(resClass->arrayDim > 1);
4629                    elementClass = dvmFindArrayClass(&resClass->descriptor[1],
4630                                        resClass->classLoader);
4631                } else if (resClass->descriptor[1] == 'L') {
4632                    assert(resClass->arrayDim == 1);
4633                    elementClass = resClass->elementClass;
4634                } else {
4635                    LOG_VFY("VFY: aget-object on non-ref array class (%s)",
4636                        resClass->descriptor);
4637                    failure = VERIFY_ERROR_GENERIC;
4638                    break;
4639                }
4640
4641                dstType = regTypeFromClass(elementClass);
4642            } else {
4643                /*
4644                 * The array reference is NULL, so the current code path will
4645                 * throw an exception.  For proper merging with later code
4646                 * paths, and correct handling of "if-eqz" tests on the
4647                 * result of the array get, we want to treat this as a null
4648                 * reference.
4649                 */
4650                dstType = kRegTypeZero;
4651            }
4652            setRegisterType(workLine, decInsn.vA, dstType);
4653        }
4654        break;
4655    case OP_APUT:
4656        tmpType = kRegTypeInteger;
4657        goto aput_1nr_common;
4658    case OP_APUT_BOOLEAN:
4659        tmpType = kRegTypeBoolean;
4660        goto aput_1nr_common;
4661    case OP_APUT_BYTE:
4662        tmpType = kRegTypeByte;
4663        goto aput_1nr_common;
4664    case OP_APUT_CHAR:
4665        tmpType = kRegTypeChar;
4666        goto aput_1nr_common;
4667    case OP_APUT_SHORT:
4668        tmpType = kRegTypeShort;
4669        goto aput_1nr_common;
4670aput_1nr_common:
4671        {
4672            RegType srcType, dstType, indexType;
4673
4674            indexType = getRegisterType(workLine, decInsn.vC);
4675            checkArrayIndexType(meth, indexType, &failure);
4676            if (!VERIFY_OK(failure))
4677                break;
4678
4679            resClass = getClassFromRegister(workLine, decInsn.vB, &failure);
4680            if (!VERIFY_OK(failure))
4681                break;
4682
4683            /* resClass can be null if the reg type is Zero */
4684            if (resClass == NULL)
4685                break;
4686
4687            if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4688                resClass->elementClass->primitiveType == PRIM_NOT)
4689            {
4690                LOG_VFY("VFY: invalid aput-1nr on %s", resClass->descriptor);
4691                failure = VERIFY_ERROR_GENERIC;
4692                break;
4693            }
4694
4695            /* verify that instruction matches array */
4696            dstType = primitiveTypeToRegType(
4697                                    resClass->elementClass->primitiveType);
4698
4699            /* correct if float */
4700            if (dstType == kRegTypeFloat)
4701                tmpType = kRegTypeFloat;
4702
4703            /* make sure the source register has the correct type */
4704            srcType = getRegisterType(workLine, decInsn.vA);
4705            if (!canConvertTo1nr(srcType, tmpType)) {
4706                LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)",
4707                    srcType, tmpType);
4708                failure = VERIFY_ERROR_GENERIC;
4709                break;
4710            }
4711
4712            verifyRegisterType(workLine, decInsn.vA, dstType, &failure);
4713
4714            if (!VERIFY_OK(failure) || dstType == kRegTypeUnknown ||
4715                !checkFieldArrayStore1nr(tmpType, dstType)) {
4716                LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)",
4717                        resClass->descriptor, tmpType, dstType);
4718                failure = VERIFY_ERROR_GENERIC;
4719                break;
4720            }
4721        }
4722        break;
4723    case OP_APUT_WIDE:
4724        tmpType = getRegisterType(workLine, decInsn.vC);
4725        checkArrayIndexType(meth, tmpType, &failure);
4726        if (!VERIFY_OK(failure))
4727            break;
4728
4729        resClass = getClassFromRegister(workLine, decInsn.vB, &failure);
4730        if (!VERIFY_OK(failure))
4731            break;
4732        if (resClass != NULL) {
4733            /* verify the class and try to refine "dstType" */
4734            if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4735                resClass->elementClass->primitiveType == PRIM_NOT)
4736            {
4737                LOG_VFY("VFY: invalid aput-wide on %s",
4738                        resClass->descriptor);
4739                failure = VERIFY_ERROR_GENERIC;
4740                break;
4741            }
4742
4743            switch (resClass->elementClass->primitiveType) {
4744            case PRIM_LONG:
4745                verifyRegisterType(workLine, decInsn.vA, kRegTypeLongLo, &failure);
4746                break;
4747            case PRIM_DOUBLE:
4748                verifyRegisterType(workLine, decInsn.vA, kRegTypeDoubleLo, &failure);
4749                break;
4750            default:
4751                LOG_VFY("VFY: invalid aput-wide on %s",
4752                        resClass->descriptor);
4753                failure = VERIFY_ERROR_GENERIC;
4754                break;
4755            }
4756        }
4757        break;
4758    case OP_APUT_OBJECT:
4759        tmpType = getRegisterType(workLine, decInsn.vC);
4760        checkArrayIndexType(meth, tmpType, &failure);
4761        if (!VERIFY_OK(failure))
4762            break;
4763
4764        /* get the ref we're storing; Zero is okay, Uninit is not */
4765        resClass = getClassFromRegister(workLine, decInsn.vA, &failure);
4766        if (!VERIFY_OK(failure))
4767            break;
4768        if (resClass != NULL) {
4769            ClassObject* arrayClass;
4770            ClassObject* elementClass;
4771
4772            /*
4773             * Get the array class.  If the array ref is null, we won't
4774             * have type information (and we'll crash at runtime with a
4775             * null pointer exception).
4776             */
4777            arrayClass = getClassFromRegister(workLine, decInsn.vB, &failure);
4778
4779            if (arrayClass != NULL) {
4780                /* see if the array holds a compatible type */
4781                if (!dvmIsArrayClass(arrayClass)) {
4782                    LOG_VFY("VFY: invalid aput-object on %s",
4783                            arrayClass->descriptor);
4784                    failure = VERIFY_ERROR_GENERIC;
4785                    break;
4786                }
4787
4788                /*
4789                 * Find the element class.  resClass->elementClass indicates
4790                 * the basic type, which won't be what we want for a
4791                 * multi-dimensional array.
4792                 *
4793                 * All we want to check here is that the element type is a
4794                 * reference class.  We *don't* check instanceof here, because
4795                 * you can still put a String into a String[] after the latter
4796                 * has been cast to an Object[].
4797                 */
4798                if (arrayClass->descriptor[1] == '[') {
4799                    assert(arrayClass->arrayDim > 1);
4800                    elementClass = dvmFindArrayClass(&arrayClass->descriptor[1],
4801                                        arrayClass->classLoader);
4802                } else {
4803                    assert(arrayClass->arrayDim == 1);
4804                    elementClass = arrayClass->elementClass;
4805                }
4806                if (elementClass->primitiveType != PRIM_NOT) {
4807                    LOG_VFY("VFY: invalid aput-object of %s into %s",
4808                            resClass->descriptor, arrayClass->descriptor);
4809                    failure = VERIFY_ERROR_GENERIC;
4810                    break;
4811                }
4812            }
4813        }
4814        break;
4815
4816    case OP_IGET:
4817    case OP_IGET_JUMBO:
4818        tmpType = kRegTypeInteger;
4819        goto iget_1nr_common;
4820    case OP_IGET_BOOLEAN:
4821    case OP_IGET_BOOLEAN_JUMBO:
4822        tmpType = kRegTypeBoolean;
4823        goto iget_1nr_common;
4824    case OP_IGET_BYTE:
4825    case OP_IGET_BYTE_JUMBO:
4826        tmpType = kRegTypeByte;
4827        goto iget_1nr_common;
4828    case OP_IGET_CHAR:
4829    case OP_IGET_CHAR_JUMBO:
4830        tmpType = kRegTypeChar;
4831        goto iget_1nr_common;
4832    case OP_IGET_SHORT:
4833    case OP_IGET_SHORT_JUMBO:
4834        tmpType = kRegTypeShort;
4835        goto iget_1nr_common;
4836iget_1nr_common:
4837        {
4838            InstField* instField;
4839            RegType objType, fieldType;
4840
4841            objType = getRegisterType(workLine, decInsn.vB);
4842            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4843                            &failure);
4844            if (!VERIFY_OK(failure))
4845                break;
4846
4847            /* make sure the field's type is compatible with expectation */
4848            fieldType = primSigCharToRegType(instField->signature[0]);
4849
4850            /* correct if float */
4851            if (fieldType == kRegTypeFloat)
4852                tmpType = kRegTypeFloat;
4853
4854            if (fieldType == kRegTypeUnknown ||
4855                !checkFieldArrayStore1nr(tmpType, fieldType))
4856            {
4857                LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)",
4858                        instField->clazz->descriptor,
4859                        instField->name, tmpType, fieldType);
4860                failure = VERIFY_ERROR_GENERIC;
4861                break;
4862            }
4863
4864            setRegisterType(workLine, decInsn.vA, tmpType);
4865        }
4866        break;
4867    case OP_IGET_WIDE:
4868    case OP_IGET_WIDE_JUMBO:
4869        {
4870            RegType dstType;
4871            InstField* instField;
4872            RegType objType;
4873
4874            objType = getRegisterType(workLine, decInsn.vB);
4875            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4876                            &failure);
4877            if (!VERIFY_OK(failure))
4878                break;
4879            /* check the type, which should be prim */
4880            switch (instField->signature[0]) {
4881            case 'D':
4882                dstType = kRegTypeDoubleLo;
4883                break;
4884            case 'J':
4885                dstType = kRegTypeLongLo;
4886                break;
4887            default:
4888                LOG_VFY("VFY: invalid iget-wide of %s.%s",
4889                        instField->clazz->descriptor,
4890                        instField->name);
4891                dstType = kRegTypeUnknown;
4892                failure = VERIFY_ERROR_GENERIC;
4893                break;
4894            }
4895            if (VERIFY_OK(failure)) {
4896                setRegisterType(workLine, decInsn.vA, dstType);
4897            }
4898        }
4899        break;
4900    case OP_IGET_OBJECT:
4901    case OP_IGET_OBJECT_JUMBO:
4902        {
4903            ClassObject* fieldClass;
4904            InstField* instField;
4905            RegType objType;
4906
4907            objType = getRegisterType(workLine, decInsn.vB);
4908            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4909                            &failure);
4910            if (!VERIFY_OK(failure))
4911                break;
4912            fieldClass = getFieldClass(meth, instField);
4913            if (fieldClass == NULL) {
4914                /* class not found or primitive type */
4915                LOG_VFY("VFY: unable to recover field class from '%s'",
4916                    instField->signature);
4917                failure = VERIFY_ERROR_GENERIC;
4918                break;
4919            }
4920            if (VERIFY_OK(failure)) {
4921                assert(!dvmIsPrimitiveClass(fieldClass));
4922                setRegisterType(workLine, decInsn.vA,
4923                    regTypeFromClass(fieldClass));
4924            }
4925        }
4926        break;
4927    case OP_IPUT:
4928    case OP_IPUT_JUMBO:
4929        tmpType = kRegTypeInteger;
4930        goto iput_1nr_common;
4931    case OP_IPUT_BOOLEAN:
4932    case OP_IPUT_BOOLEAN_JUMBO:
4933        tmpType = kRegTypeBoolean;
4934        goto iput_1nr_common;
4935    case OP_IPUT_BYTE:
4936    case OP_IPUT_BYTE_JUMBO:
4937        tmpType = kRegTypeByte;
4938        goto iput_1nr_common;
4939    case OP_IPUT_CHAR:
4940    case OP_IPUT_CHAR_JUMBO:
4941        tmpType = kRegTypeChar;
4942        goto iput_1nr_common;
4943    case OP_IPUT_SHORT:
4944    case OP_IPUT_SHORT_JUMBO:
4945        tmpType = kRegTypeShort;
4946        goto iput_1nr_common;
4947iput_1nr_common:
4948        {
4949            RegType srcType, fieldType, objType;
4950            InstField* instField;
4951
4952            objType = getRegisterType(workLine, decInsn.vB);
4953            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4954                            &failure);
4955            if (!VERIFY_OK(failure))
4956                break;
4957            checkFinalFieldAccess(meth, instField, &failure);
4958            if (!VERIFY_OK(failure))
4959                break;
4960
4961            /* get type of field we're storing into */
4962            fieldType = primSigCharToRegType(instField->signature[0]);
4963            srcType = getRegisterType(workLine, decInsn.vA);
4964
4965            /* correct if float */
4966            if (fieldType == kRegTypeFloat)
4967                tmpType = kRegTypeFloat;
4968
4969            /*
4970             * javac generates synthetic functions that write byte values
4971             * into boolean fields.
4972             */
4973            if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte)
4974                tmpType = kRegTypeByte;
4975            if (fieldType == kRegTypeBoolean && srcType == kRegTypeByte)
4976                fieldType = kRegTypeByte;
4977
4978            /* make sure the source register has the correct type */
4979            if (!canConvertTo1nr(srcType, tmpType)) {
4980                LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)",
4981                    srcType, tmpType);
4982                failure = VERIFY_ERROR_GENERIC;
4983                break;
4984            }
4985
4986            verifyRegisterType(workLine, decInsn.vA, fieldType, &failure);
4987
4988            if (!VERIFY_OK(failure) || fieldType == kRegTypeUnknown ||
4989                !checkFieldArrayStore1nr(tmpType, fieldType))
4990            {
4991                LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)",
4992                        instField->clazz->descriptor,
4993                        instField->name, tmpType, fieldType);
4994                failure = VERIFY_ERROR_GENERIC;
4995                break;
4996            }
4997        }
4998        break;
4999    case OP_IPUT_WIDE:
5000    case OP_IPUT_WIDE_JUMBO:
5001        InstField* instField;
5002        RegType objType;
5003
5004        objType = getRegisterType(workLine, decInsn.vB);
5005        instField = getInstField(meth, uninitMap, objType, decInsn.vC,
5006                        &failure);
5007        if (!VERIFY_OK(failure))
5008            break;
5009        checkFinalFieldAccess(meth, instField, &failure);
5010        if (!VERIFY_OK(failure))
5011            break;
5012
5013        /* check the type, which should be prim */
5014        switch (instField->signature[0]) {
5015        case 'D':
5016            verifyRegisterType(workLine, decInsn.vA, kRegTypeDoubleLo, &failure);
5017            break;
5018        case 'J':
5019            verifyRegisterType(workLine, decInsn.vA, kRegTypeLongLo, &failure);
5020            break;
5021        default:
5022            LOG_VFY("VFY: invalid iput-wide of %s.%s",
5023                    instField->clazz->descriptor,
5024                    instField->name);
5025            failure = VERIFY_ERROR_GENERIC;
5026            break;
5027        }
5028        break;
5029    case OP_IPUT_OBJECT:
5030    case OP_IPUT_OBJECT_JUMBO:
5031        {
5032            ClassObject* fieldClass;
5033            ClassObject* valueClass;
5034            InstField* instField;
5035            RegType objType, valueType;
5036
5037            objType = getRegisterType(workLine, decInsn.vB);
5038            instField = getInstField(meth, uninitMap, objType, decInsn.vC,
5039                            &failure);
5040            if (!VERIFY_OK(failure))
5041                break;
5042            checkFinalFieldAccess(meth, instField, &failure);
5043            if (!VERIFY_OK(failure))
5044                break;
5045
5046            fieldClass = getFieldClass(meth, instField);
5047            if (fieldClass == NULL) {
5048                LOG_VFY("VFY: unable to recover field class from '%s'",
5049                    instField->signature);
5050                failure = VERIFY_ERROR_GENERIC;
5051                break;
5052            }
5053
5054            valueType = getRegisterType(workLine, decInsn.vA);
5055            if (!regTypeIsReference(valueType)) {
5056                LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)",
5057                        decInsn.vA, instField->name,
5058                        fieldClass->descriptor);
5059                failure = VERIFY_ERROR_GENERIC;
5060                break;
5061            }
5062            if (valueType != kRegTypeZero) {
5063                valueClass = regTypeInitializedReferenceToClass(valueType);
5064                if (valueClass == NULL) {
5065                    LOG_VFY("VFY: storing uninit ref v%d into ref field",
5066                        decInsn.vA);
5067                    failure = VERIFY_ERROR_GENERIC;
5068                    break;
5069                }
5070                /* allow if field is any interface or field is base class */
5071                if (!dvmIsInterfaceClass(fieldClass) &&
5072                    !dvmInstanceof(valueClass, fieldClass))
5073                {
5074                    LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)",
5075                            valueClass->descriptor, fieldClass->descriptor,
5076                            instField->clazz->descriptor,
5077                            instField->name);
5078                    failure = VERIFY_ERROR_GENERIC;
5079                    break;
5080                }
5081            }
5082        }
5083        break;
5084
5085    case OP_SGET:
5086    case OP_SGET_JUMBO:
5087        tmpType = kRegTypeInteger;
5088        goto sget_1nr_common;
5089    case OP_SGET_BOOLEAN:
5090    case OP_SGET_BOOLEAN_JUMBO:
5091        tmpType = kRegTypeBoolean;
5092        goto sget_1nr_common;
5093    case OP_SGET_BYTE:
5094    case OP_SGET_BYTE_JUMBO:
5095        tmpType = kRegTypeByte;
5096        goto sget_1nr_common;
5097    case OP_SGET_CHAR:
5098    case OP_SGET_CHAR_JUMBO:
5099        tmpType = kRegTypeChar;
5100        goto sget_1nr_common;
5101    case OP_SGET_SHORT:
5102    case OP_SGET_SHORT_JUMBO:
5103        tmpType = kRegTypeShort;
5104        goto sget_1nr_common;
5105sget_1nr_common:
5106        {
5107            StaticField* staticField;
5108            RegType fieldType;
5109
5110            staticField = getStaticField(meth, decInsn.vB, &failure);
5111            if (!VERIFY_OK(failure))
5112                break;
5113
5114            /*
5115             * Make sure the field's type is compatible with expectation.
5116             * We can get ourselves into trouble if we mix & match loads
5117             * and stores with different widths, so rather than just checking
5118             * "canConvertTo1nr" we require that the field types have equal
5119             * widths.
5120             */
5121            fieldType = primSigCharToRegType(staticField->signature[0]);
5122
5123            /* correct if float */
5124            if (fieldType == kRegTypeFloat)
5125                tmpType = kRegTypeFloat;
5126
5127            if (!checkFieldArrayStore1nr(tmpType, fieldType)) {
5128                LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)",
5129                    staticField->clazz->descriptor,
5130                    staticField->name, tmpType, fieldType);
5131                failure = VERIFY_ERROR_GENERIC;
5132                break;
5133            }
5134
5135            setRegisterType(workLine, decInsn.vA, tmpType);
5136        }
5137        break;
5138    case OP_SGET_WIDE:
5139    case OP_SGET_WIDE_JUMBO:
5140        {
5141            StaticField* staticField;
5142            RegType dstType;
5143
5144            staticField = getStaticField(meth, decInsn.vB, &failure);
5145            if (!VERIFY_OK(failure))
5146                break;
5147            /* check the type, which should be prim */
5148            switch (staticField->signature[0]) {
5149            case 'D':
5150                dstType = kRegTypeDoubleLo;
5151                break;
5152            case 'J':
5153                dstType = kRegTypeLongLo;
5154                break;
5155            default:
5156                LOG_VFY("VFY: invalid sget-wide of %s.%s",
5157                        staticField->clazz->descriptor,
5158                        staticField->name);
5159                dstType = kRegTypeUnknown;
5160                failure = VERIFY_ERROR_GENERIC;
5161                break;
5162            }
5163            if (VERIFY_OK(failure)) {
5164                setRegisterType(workLine, decInsn.vA, dstType);
5165            }
5166        }
5167        break;
5168    case OP_SGET_OBJECT:
5169    case OP_SGET_OBJECT_JUMBO:
5170        {
5171            StaticField* staticField;
5172            ClassObject* fieldClass;
5173
5174            staticField = getStaticField(meth, decInsn.vB, &failure);
5175            if (!VERIFY_OK(failure))
5176                break;
5177            fieldClass = getFieldClass(meth, staticField);
5178            if (fieldClass == NULL) {
5179                LOG_VFY("VFY: unable to recover field class from '%s'",
5180                    staticField->signature);
5181                failure = VERIFY_ERROR_GENERIC;
5182                break;
5183            }
5184            if (dvmIsPrimitiveClass(fieldClass)) {
5185                LOG_VFY("VFY: attempt to get prim field with sget-object");
5186                failure = VERIFY_ERROR_GENERIC;
5187                break;
5188            }
5189            setRegisterType(workLine, decInsn.vA, regTypeFromClass(fieldClass));
5190        }
5191        break;
5192    case OP_SPUT:
5193    case OP_SPUT_JUMBO:
5194        tmpType = kRegTypeInteger;
5195        goto sput_1nr_common;
5196    case OP_SPUT_BOOLEAN:
5197    case OP_SPUT_BOOLEAN_JUMBO:
5198        tmpType = kRegTypeBoolean;
5199        goto sput_1nr_common;
5200    case OP_SPUT_BYTE:
5201    case OP_SPUT_BYTE_JUMBO:
5202        tmpType = kRegTypeByte;
5203        goto sput_1nr_common;
5204    case OP_SPUT_CHAR:
5205    case OP_SPUT_CHAR_JUMBO:
5206        tmpType = kRegTypeChar;
5207        goto sput_1nr_common;
5208    case OP_SPUT_SHORT:
5209    case OP_SPUT_SHORT_JUMBO:
5210        tmpType = kRegTypeShort;
5211        goto sput_1nr_common;
5212sput_1nr_common:
5213        {
5214            RegType srcType, fieldType;
5215            StaticField* staticField;
5216
5217            staticField = getStaticField(meth, decInsn.vB, &failure);
5218            if (!VERIFY_OK(failure))
5219                break;
5220            checkFinalFieldAccess(meth, staticField, &failure);
5221            if (!VERIFY_OK(failure))
5222                break;
5223
5224            /*
5225             * Get type of field we're storing into.  We know that the
5226             * contents of the register match the instruction, but we also
5227             * need to ensure that the instruction matches the field type.
5228             * Using e.g. sput-short to write into a 32-bit integer field
5229             * can lead to trouble if we do 16-bit writes.
5230             */
5231            fieldType = primSigCharToRegType(staticField->signature[0]);
5232            srcType = getRegisterType(workLine, decInsn.vA);
5233
5234            /* correct if float */
5235            if (fieldType == kRegTypeFloat)
5236                tmpType = kRegTypeFloat;
5237
5238            /*
5239             * javac generates synthetic functions that write byte values
5240             * into boolean fields.
5241             */
5242            if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte)
5243                tmpType = kRegTypeByte;
5244            if (fieldType == kRegTypeBoolean && srcType == kRegTypeByte)
5245                fieldType = kRegTypeByte;
5246
5247            /* make sure the source register has the correct type */
5248            if (!canConvertTo1nr(srcType, tmpType)) {
5249                LOG_VFY("VFY: invalid reg type %d on sput instr (need %d)",
5250                    srcType, tmpType);
5251                failure = VERIFY_ERROR_GENERIC;
5252                break;
5253            }
5254
5255            verifyRegisterType(workLine, decInsn.vA, fieldType, &failure);
5256
5257            if (!VERIFY_OK(failure) || fieldType == kRegTypeUnknown ||
5258                !checkFieldArrayStore1nr(tmpType, fieldType)) {
5259                LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)",
5260                    staticField->clazz->descriptor,
5261                    staticField->name, tmpType, fieldType);
5262                failure = VERIFY_ERROR_GENERIC;
5263                break;
5264            }
5265        }
5266        break;
5267    case OP_SPUT_WIDE:
5268    case OP_SPUT_WIDE_JUMBO:
5269        StaticField* staticField;
5270
5271        staticField = getStaticField(meth, decInsn.vB, &failure);
5272        if (!VERIFY_OK(failure))
5273            break;
5274        checkFinalFieldAccess(meth, staticField, &failure);
5275        if (!VERIFY_OK(failure))
5276            break;
5277
5278        /* check the type, which should be prim */
5279        switch (staticField->signature[0]) {
5280        case 'D':
5281            verifyRegisterType(workLine, decInsn.vA, kRegTypeDoubleLo, &failure);
5282            break;
5283        case 'J':
5284            verifyRegisterType(workLine, decInsn.vA, kRegTypeLongLo, &failure);
5285            break;
5286        default:
5287            LOG_VFY("VFY: invalid sput-wide of %s.%s",
5288                    staticField->clazz->descriptor,
5289                    staticField->name);
5290            failure = VERIFY_ERROR_GENERIC;
5291            break;
5292        }
5293        break;
5294    case OP_SPUT_OBJECT:
5295    case OP_SPUT_OBJECT_JUMBO:
5296        {
5297            ClassObject* fieldClass;
5298            ClassObject* valueClass;
5299            StaticField* staticField;
5300            RegType valueType;
5301
5302            staticField = getStaticField(meth, decInsn.vB, &failure);
5303            if (!VERIFY_OK(failure))
5304                break;
5305            checkFinalFieldAccess(meth, staticField, &failure);
5306            if (!VERIFY_OK(failure))
5307                break;
5308
5309            fieldClass = getFieldClass(meth, staticField);
5310            if (fieldClass == NULL) {
5311                LOG_VFY("VFY: unable to recover field class from '%s'",
5312                    staticField->signature);
5313                failure = VERIFY_ERROR_GENERIC;
5314                break;
5315            }
5316
5317            valueType = getRegisterType(workLine, decInsn.vA);
5318            if (!regTypeIsReference(valueType)) {
5319                LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)",
5320                        decInsn.vA, staticField->name,
5321                        fieldClass->descriptor);
5322                failure = VERIFY_ERROR_GENERIC;
5323                break;
5324            }
5325            if (valueType != kRegTypeZero) {
5326                valueClass = regTypeInitializedReferenceToClass(valueType);
5327                if (valueClass == NULL) {
5328                    LOG_VFY("VFY: storing uninit ref v%d into ref field",
5329                        decInsn.vA);
5330                    failure = VERIFY_ERROR_GENERIC;
5331                    break;
5332                }
5333                /* allow if field is any interface or field is base class */
5334                if (!dvmIsInterfaceClass(fieldClass) &&
5335                    !dvmInstanceof(valueClass, fieldClass))
5336                {
5337                    LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)",
5338                            valueClass->descriptor, fieldClass->descriptor,
5339                            staticField->clazz->descriptor,
5340                            staticField->name);
5341                    failure = VERIFY_ERROR_GENERIC;
5342                    break;
5343                }
5344            }
5345        }
5346        break;
5347
5348    case OP_INVOKE_VIRTUAL:
5349    case OP_INVOKE_VIRTUAL_RANGE:
5350    case OP_INVOKE_VIRTUAL_JUMBO:
5351    case OP_INVOKE_SUPER:
5352    case OP_INVOKE_SUPER_RANGE:
5353    case OP_INVOKE_SUPER_JUMBO:
5354        {
5355            Method* calledMethod;
5356            RegType returnType;
5357            bool isRange;
5358            bool isSuper;
5359
5360            isRange =  (decInsn.opcode == OP_INVOKE_VIRTUAL_RANGE ||
5361                        decInsn.opcode == OP_INVOKE_VIRTUAL_JUMBO ||
5362                        decInsn.opcode == OP_INVOKE_SUPER_RANGE ||
5363                        decInsn.opcode == OP_INVOKE_SUPER_JUMBO);
5364            isSuper =  (decInsn.opcode == OP_INVOKE_SUPER ||
5365                        decInsn.opcode == OP_INVOKE_SUPER_RANGE ||
5366                        decInsn.opcode == OP_INVOKE_SUPER_JUMBO);
5367
5368            calledMethod = verifyInvocationArgs(meth, workLine, insnRegCount,
5369                            &decInsn, uninitMap, METHOD_VIRTUAL, isRange,
5370                            isSuper, &failure);
5371            if (!VERIFY_OK(failure))
5372                break;
5373            returnType = getMethodReturnType(calledMethod);
5374            setResultRegisterType(workLine, insnRegCount, returnType);
5375            justSetResult = true;
5376        }
5377        break;
5378    case OP_INVOKE_DIRECT:
5379    case OP_INVOKE_DIRECT_RANGE:
5380    case OP_INVOKE_DIRECT_JUMBO:
5381        {
5382            RegType returnType;
5383            Method* calledMethod;
5384            bool isRange;
5385
5386            isRange =  (decInsn.opcode == OP_INVOKE_DIRECT_RANGE ||
5387                        decInsn.opcode == OP_INVOKE_DIRECT_JUMBO);
5388            calledMethod = verifyInvocationArgs(meth, workLine, insnRegCount,
5389                            &decInsn, uninitMap, METHOD_DIRECT, isRange,
5390                            false, &failure);
5391            if (!VERIFY_OK(failure))
5392                break;
5393
5394            /*
5395             * Some additional checks when calling <init>.  We know from
5396             * the invocation arg check that the "this" argument is an
5397             * instance of calledMethod->clazz.  Now we further restrict
5398             * that to require that calledMethod->clazz is the same as
5399             * this->clazz or this->super, allowing the latter only if
5400             * the "this" argument is the same as the "this" argument to
5401             * this method (which implies that we're in <init> ourselves).
5402             */
5403            if (isInitMethod(calledMethod)) {
5404                RegType thisType;
5405                thisType = getInvocationThis(workLine, &decInsn, &failure);
5406                if (!VERIFY_OK(failure))
5407                    break;
5408
5409                /* no null refs allowed (?) */
5410                if (thisType == kRegTypeZero) {
5411                    LOG_VFY("VFY: unable to initialize null ref");
5412                    failure = VERIFY_ERROR_GENERIC;
5413                    break;
5414                }
5415
5416                ClassObject* thisClass;
5417
5418                thisClass = regTypeReferenceToClass(thisType, uninitMap);
5419                assert(thisClass != NULL);
5420
5421                /* must be in same class or in superclass */
5422                if (calledMethod->clazz == thisClass->super) {
5423                    if (thisClass != meth->clazz) {
5424                        LOG_VFY("VFY: invoke-direct <init> on super only "
5425                            "allowed for 'this' in <init>");
5426                        failure = VERIFY_ERROR_GENERIC;
5427                        break;
5428                    }
5429                }  else if (calledMethod->clazz != thisClass) {
5430                    LOG_VFY("VFY: invoke-direct <init> must be on current "
5431                            "class or super");
5432                    failure = VERIFY_ERROR_GENERIC;
5433                    break;
5434                }
5435
5436                /* arg must be an uninitialized reference */
5437                if (!regTypeIsUninitReference(thisType)) {
5438                    LOG_VFY("VFY: can only initialize the uninitialized");
5439                    failure = VERIFY_ERROR_GENERIC;
5440                    break;
5441                }
5442
5443                /*
5444                 * Replace the uninitialized reference with an initialized
5445                 * one, and clear the entry in the uninit map.  We need to
5446                 * do this for all registers that have the same object
5447                 * instance in them, not just the "this" register.
5448                 */
5449                markRefsAsInitialized(workLine, insnRegCount, uninitMap,
5450                    thisType, &failure);
5451                if (!VERIFY_OK(failure))
5452                    break;
5453            }
5454            returnType = getMethodReturnType(calledMethod);
5455            setResultRegisterType(workLine, insnRegCount, returnType);
5456            justSetResult = true;
5457        }
5458        break;
5459    case OP_INVOKE_STATIC:
5460    case OP_INVOKE_STATIC_RANGE:
5461    case OP_INVOKE_STATIC_JUMBO:
5462        {
5463            RegType returnType;
5464            Method* calledMethod;
5465            bool isRange;
5466
5467            isRange =  (decInsn.opcode == OP_INVOKE_STATIC_RANGE ||
5468                        decInsn.opcode == OP_INVOKE_STATIC_JUMBO);
5469            calledMethod = verifyInvocationArgs(meth, workLine, insnRegCount,
5470                            &decInsn, uninitMap, METHOD_STATIC, isRange,
5471                            false, &failure);
5472            if (!VERIFY_OK(failure))
5473                break;
5474
5475            returnType = getMethodReturnType(calledMethod);
5476            setResultRegisterType(workLine, insnRegCount, returnType);
5477            justSetResult = true;
5478        }
5479        break;
5480    case OP_INVOKE_INTERFACE:
5481    case OP_INVOKE_INTERFACE_RANGE:
5482    case OP_INVOKE_INTERFACE_JUMBO:
5483        {
5484            RegType /*thisType,*/ returnType;
5485            Method* absMethod;
5486            bool isRange;
5487
5488            isRange =  (decInsn.opcode == OP_INVOKE_INTERFACE_RANGE ||
5489                        decInsn.opcode == OP_INVOKE_INTERFACE_JUMBO);
5490            absMethod = verifyInvocationArgs(meth, workLine, insnRegCount,
5491                            &decInsn, uninitMap, METHOD_INTERFACE, isRange,
5492                            false, &failure);
5493            if (!VERIFY_OK(failure))
5494                break;
5495
5496#if 0       /* can't do this here, fails on dalvik test 052-verifier-fun */
5497            /*
5498             * Get the type of the "this" arg, which should always be an
5499             * interface class.  Because we don't do a full merge on
5500             * interface classes, this might have reduced to Object.
5501             */
5502            thisType = getInvocationThis(workLine, &decInsn, &failure);
5503            if (!VERIFY_OK(failure))
5504                break;
5505
5506            if (thisType == kRegTypeZero) {
5507                /* null pointer always passes (and always fails at runtime) */
5508            } else {
5509                ClassObject* thisClass;
5510
5511                thisClass = regTypeInitializedReferenceToClass(thisType);
5512                if (thisClass == NULL) {
5513                    LOG_VFY("VFY: interface call on uninitialized");
5514                    failure = VERIFY_ERROR_GENERIC;
5515                    break;
5516                }
5517
5518                /*
5519                 * Either "thisClass" needs to be the interface class that
5520                 * defined absMethod, or absMethod's class needs to be one
5521                 * of the interfaces implemented by "thisClass".  (Or, if
5522                 * we couldn't complete the merge, this will be Object.)
5523                 */
5524                if (thisClass != absMethod->clazz &&
5525                    thisClass != gDvm.classJavaLangObject &&
5526                    !dvmImplements(thisClass, absMethod->clazz))
5527                {
5528                    LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces",
5529                            absMethod->name, thisClass->descriptor);
5530                    failure = VERIFY_ERROR_GENERIC;
5531                    break;
5532                }
5533            }
5534#endif
5535
5536            /*
5537             * We don't have an object instance, so we can't find the
5538             * concrete method.  However, all of the type information is
5539             * in the abstract method, so we're good.
5540             */
5541            returnType = getMethodReturnType(absMethod);
5542            setResultRegisterType(workLine, insnRegCount, returnType);
5543            justSetResult = true;
5544        }
5545        break;
5546
5547    case OP_NEG_INT:
5548    case OP_NOT_INT:
5549        checkUnop(workLine, &decInsn,
5550            kRegTypeInteger, kRegTypeInteger, &failure);
5551        break;
5552    case OP_NEG_LONG:
5553    case OP_NOT_LONG:
5554        checkUnop(workLine, &decInsn,
5555            kRegTypeLongLo, kRegTypeLongLo, &failure);
5556        break;
5557    case OP_NEG_FLOAT:
5558        checkUnop(workLine, &decInsn,
5559            kRegTypeFloat, kRegTypeFloat, &failure);
5560        break;
5561    case OP_NEG_DOUBLE:
5562        checkUnop(workLine, &decInsn,
5563            kRegTypeDoubleLo, kRegTypeDoubleLo, &failure);
5564        break;
5565    case OP_INT_TO_LONG:
5566        checkUnop(workLine, &decInsn,
5567            kRegTypeLongLo, kRegTypeInteger, &failure);
5568        break;
5569    case OP_INT_TO_FLOAT:
5570        checkUnop(workLine, &decInsn,
5571            kRegTypeFloat, kRegTypeInteger, &failure);
5572        break;
5573    case OP_INT_TO_DOUBLE:
5574        checkUnop(workLine, &decInsn,
5575            kRegTypeDoubleLo, kRegTypeInteger, &failure);
5576        break;
5577    case OP_LONG_TO_INT:
5578        checkUnop(workLine, &decInsn,
5579            kRegTypeInteger, kRegTypeLongLo, &failure);
5580        break;
5581    case OP_LONG_TO_FLOAT:
5582        checkUnop(workLine, &decInsn,
5583            kRegTypeFloat, kRegTypeLongLo, &failure);
5584        break;
5585    case OP_LONG_TO_DOUBLE:
5586        checkUnop(workLine, &decInsn,
5587            kRegTypeDoubleLo, kRegTypeLongLo, &failure);
5588        break;
5589    case OP_FLOAT_TO_INT:
5590        checkUnop(workLine, &decInsn,
5591            kRegTypeInteger, kRegTypeFloat, &failure);
5592        break;
5593    case OP_FLOAT_TO_LONG:
5594        checkUnop(workLine, &decInsn,
5595            kRegTypeLongLo, kRegTypeFloat, &failure);
5596        break;
5597    case OP_FLOAT_TO_DOUBLE:
5598        checkUnop(workLine, &decInsn,
5599            kRegTypeDoubleLo, kRegTypeFloat, &failure);
5600        break;
5601    case OP_DOUBLE_TO_INT:
5602        checkUnop(workLine, &decInsn,
5603            kRegTypeInteger, kRegTypeDoubleLo, &failure);
5604        break;
5605    case OP_DOUBLE_TO_LONG:
5606        checkUnop(workLine, &decInsn,
5607            kRegTypeLongLo, kRegTypeDoubleLo, &failure);
5608        break;
5609    case OP_DOUBLE_TO_FLOAT:
5610        checkUnop(workLine, &decInsn,
5611            kRegTypeFloat, kRegTypeDoubleLo, &failure);
5612        break;
5613    case OP_INT_TO_BYTE:
5614        checkUnop(workLine, &decInsn,
5615            kRegTypeByte, kRegTypeInteger, &failure);
5616        break;
5617    case OP_INT_TO_CHAR:
5618        checkUnop(workLine, &decInsn,
5619            kRegTypeChar, kRegTypeInteger, &failure);
5620        break;
5621    case OP_INT_TO_SHORT:
5622        checkUnop(workLine, &decInsn,
5623            kRegTypeShort, kRegTypeInteger, &failure);
5624        break;
5625
5626    case OP_ADD_INT:
5627    case OP_SUB_INT:
5628    case OP_MUL_INT:
5629    case OP_REM_INT:
5630    case OP_DIV_INT:
5631    case OP_SHL_INT:
5632    case OP_SHR_INT:
5633    case OP_USHR_INT:
5634        checkBinop(workLine, &decInsn,
5635            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
5636        break;
5637    case OP_AND_INT:
5638    case OP_OR_INT:
5639    case OP_XOR_INT:
5640        checkBinop(workLine, &decInsn,
5641            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
5642        break;
5643    case OP_ADD_LONG:
5644    case OP_SUB_LONG:
5645    case OP_MUL_LONG:
5646    case OP_DIV_LONG:
5647    case OP_REM_LONG:
5648    case OP_AND_LONG:
5649    case OP_OR_LONG:
5650    case OP_XOR_LONG:
5651        checkBinop(workLine, &decInsn,
5652            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
5653        break;
5654    case OP_SHL_LONG:
5655    case OP_SHR_LONG:
5656    case OP_USHR_LONG:
5657        /* shift distance is Int, making these different from other binops */
5658        checkBinop(workLine, &decInsn,
5659            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
5660        break;
5661    case OP_ADD_FLOAT:
5662    case OP_SUB_FLOAT:
5663    case OP_MUL_FLOAT:
5664    case OP_DIV_FLOAT:
5665    case OP_REM_FLOAT:
5666        checkBinop(workLine, &decInsn,
5667            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
5668        break;
5669    case OP_ADD_DOUBLE:
5670    case OP_SUB_DOUBLE:
5671    case OP_MUL_DOUBLE:
5672    case OP_DIV_DOUBLE:
5673    case OP_REM_DOUBLE:
5674        checkBinop(workLine, &decInsn,
5675            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
5676            &failure);
5677        break;
5678    case OP_ADD_INT_2ADDR:
5679    case OP_SUB_INT_2ADDR:
5680    case OP_MUL_INT_2ADDR:
5681    case OP_REM_INT_2ADDR:
5682    case OP_SHL_INT_2ADDR:
5683    case OP_SHR_INT_2ADDR:
5684    case OP_USHR_INT_2ADDR:
5685        checkBinop2addr(workLine, &decInsn,
5686            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
5687        break;
5688    case OP_AND_INT_2ADDR:
5689    case OP_OR_INT_2ADDR:
5690    case OP_XOR_INT_2ADDR:
5691        checkBinop2addr(workLine, &decInsn,
5692            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
5693        break;
5694    case OP_DIV_INT_2ADDR:
5695        checkBinop2addr(workLine, &decInsn,
5696            kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
5697        break;
5698    case OP_ADD_LONG_2ADDR:
5699    case OP_SUB_LONG_2ADDR:
5700    case OP_MUL_LONG_2ADDR:
5701    case OP_DIV_LONG_2ADDR:
5702    case OP_REM_LONG_2ADDR:
5703    case OP_AND_LONG_2ADDR:
5704    case OP_OR_LONG_2ADDR:
5705    case OP_XOR_LONG_2ADDR:
5706        checkBinop2addr(workLine, &decInsn,
5707            kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
5708        break;
5709    case OP_SHL_LONG_2ADDR:
5710    case OP_SHR_LONG_2ADDR:
5711    case OP_USHR_LONG_2ADDR:
5712        checkBinop2addr(workLine, &decInsn,
5713            kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
5714        break;
5715    case OP_ADD_FLOAT_2ADDR:
5716    case OP_SUB_FLOAT_2ADDR:
5717    case OP_MUL_FLOAT_2ADDR:
5718    case OP_DIV_FLOAT_2ADDR:
5719    case OP_REM_FLOAT_2ADDR:
5720        checkBinop2addr(workLine, &decInsn,
5721            kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
5722        break;
5723    case OP_ADD_DOUBLE_2ADDR:
5724    case OP_SUB_DOUBLE_2ADDR:
5725    case OP_MUL_DOUBLE_2ADDR:
5726    case OP_DIV_DOUBLE_2ADDR:
5727    case OP_REM_DOUBLE_2ADDR:
5728        checkBinop2addr(workLine, &decInsn,
5729            kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
5730            &failure);
5731        break;
5732    case OP_ADD_INT_LIT16:
5733    case OP_RSUB_INT:
5734    case OP_MUL_INT_LIT16:
5735    case OP_DIV_INT_LIT16:
5736    case OP_REM_INT_LIT16:
5737        checkLitop(workLine, &decInsn,
5738            kRegTypeInteger, kRegTypeInteger, false, &failure);
5739        break;
5740    case OP_AND_INT_LIT16:
5741    case OP_OR_INT_LIT16:
5742    case OP_XOR_INT_LIT16:
5743        checkLitop(workLine, &decInsn,
5744            kRegTypeInteger, kRegTypeInteger, true, &failure);
5745        break;
5746    case OP_ADD_INT_LIT8:
5747    case OP_RSUB_INT_LIT8:
5748    case OP_MUL_INT_LIT8:
5749    case OP_DIV_INT_LIT8:
5750    case OP_REM_INT_LIT8:
5751    case OP_SHL_INT_LIT8:
5752        checkLitop(workLine, &decInsn,
5753            kRegTypeInteger, kRegTypeInteger, false, &failure);
5754        break;
5755    case OP_SHR_INT_LIT8:
5756        tmpType = adjustForRightShift(workLine,
5757            decInsn.vB, decInsn.vC, false, &failure);
5758        checkLitop(workLine, &decInsn,
5759            tmpType, kRegTypeInteger, false, &failure);
5760        break;
5761    case OP_USHR_INT_LIT8:
5762        tmpType = adjustForRightShift(workLine,
5763            decInsn.vB, decInsn.vC, true, &failure);
5764        checkLitop(workLine, &decInsn,
5765            tmpType, kRegTypeInteger, false, &failure);
5766        break;
5767    case OP_AND_INT_LIT8:
5768    case OP_OR_INT_LIT8:
5769    case OP_XOR_INT_LIT8:
5770        checkLitop(workLine, &decInsn,
5771            kRegTypeInteger, kRegTypeInteger, true, &failure);
5772        break;
5773
5774    /*
5775     * This falls into the general category of "optimized" instructions,
5776     * which don't generally appear during verification.  Because it's
5777     * inserted in the course of verification, we can expect to see it here.
5778     */
5779    case OP_THROW_VERIFICATION_ERROR:
5780    case OP_THROW_VERIFICATION_ERROR_JUMBO:
5781        break;
5782
5783    /*
5784     * Verifying "quickened" instructions is tricky, because we have
5785     * discarded the original field/method information.  The byte offsets
5786     * and vtable indices only have meaning in the context of an object
5787     * instance.
5788     *
5789     * If a piece of code declares a local reference variable, assigns
5790     * null to it, and then issues a virtual method call on it, we
5791     * cannot evaluate the method call during verification.  This situation
5792     * isn't hard to handle, since we know the call will always result in an
5793     * NPE, and the arguments and return value don't matter.  Any code that
5794     * depends on the result of the method call is inaccessible, so the
5795     * fact that we can't fully verify anything that comes after the bad
5796     * call is not a problem.
5797     *
5798     * We must also consider the case of multiple code paths, only some of
5799     * which involve a null reference.  We can completely verify the method
5800     * if we sidestep the results of executing with a null reference.
5801     * For example, if on the first pass through the code we try to do a
5802     * virtual method invocation through a null ref, we have to skip the
5803     * method checks and have the method return a "wildcard" type (which
5804     * merges with anything to become that other thing).  The move-result
5805     * will tell us if it's a reference, single-word numeric, or double-word
5806     * value.  We continue to perform the verification, and at the end of
5807     * the function any invocations that were never fully exercised are
5808     * marked as null-only.
5809     *
5810     * We would do something similar for the field accesses.  The field's
5811     * type, once known, can be used to recover the width of short integers.
5812     * If the object reference was null, the field-get returns the "wildcard"
5813     * type, which is acceptable for any operation.
5814     */
5815    case OP_EXECUTE_INLINE:
5816    case OP_EXECUTE_INLINE_RANGE:
5817    case OP_IGET_QUICK:
5818    case OP_IGET_WIDE_QUICK:
5819    case OP_IGET_OBJECT_QUICK:
5820    case OP_IPUT_QUICK:
5821    case OP_IPUT_WIDE_QUICK:
5822    case OP_IPUT_OBJECT_QUICK:
5823    case OP_INVOKE_VIRTUAL_QUICK:
5824    case OP_INVOKE_VIRTUAL_QUICK_RANGE:
5825    case OP_INVOKE_SUPER_QUICK:
5826    case OP_INVOKE_SUPER_QUICK_RANGE:
5827        /* fall through to failure */
5828
5829    /*
5830     * These instructions are equivalent (from the verifier's point of view)
5831     * to the original form.  The change was made for correctness rather
5832     * than improved performance (except for invoke-object-init, which
5833     * provides both).  The substitution takes place after verification
5834     * completes, though, so we don't expect to see them here.
5835     */
5836    case OP_INVOKE_OBJECT_INIT_RANGE:
5837    case OP_INVOKE_OBJECT_INIT_JUMBO:
5838    case OP_RETURN_VOID_BARRIER:
5839    case OP_IGET_VOLATILE:
5840    case OP_IGET_VOLATILE_JUMBO:
5841    case OP_IGET_WIDE_VOLATILE:
5842    case OP_IGET_WIDE_VOLATILE_JUMBO:
5843    case OP_IGET_OBJECT_VOLATILE:
5844    case OP_IGET_OBJECT_VOLATILE_JUMBO:
5845    case OP_IPUT_VOLATILE:
5846    case OP_IPUT_VOLATILE_JUMBO:
5847    case OP_IPUT_WIDE_VOLATILE:
5848    case OP_IPUT_WIDE_VOLATILE_JUMBO:
5849    case OP_IPUT_OBJECT_VOLATILE:
5850    case OP_IPUT_OBJECT_VOLATILE_JUMBO:
5851    case OP_SGET_VOLATILE:
5852    case OP_SGET_VOLATILE_JUMBO:
5853    case OP_SGET_WIDE_VOLATILE:
5854    case OP_SGET_WIDE_VOLATILE_JUMBO:
5855    case OP_SGET_OBJECT_VOLATILE:
5856    case OP_SGET_OBJECT_VOLATILE_JUMBO:
5857    case OP_SPUT_VOLATILE:
5858    case OP_SPUT_VOLATILE_JUMBO:
5859    case OP_SPUT_WIDE_VOLATILE:
5860    case OP_SPUT_WIDE_VOLATILE_JUMBO:
5861    case OP_SPUT_OBJECT_VOLATILE:
5862    case OP_SPUT_OBJECT_VOLATILE_JUMBO:
5863        /* fall through to failure */
5864
5865    /* these should never appear during verification */
5866    case OP_UNUSED_3E:
5867    case OP_UNUSED_3F:
5868    case OP_UNUSED_40:
5869    case OP_UNUSED_41:
5870    case OP_UNUSED_42:
5871    case OP_UNUSED_43:
5872    case OP_UNUSED_73:
5873    case OP_UNUSED_79:
5874    case OP_UNUSED_7A:
5875    case OP_BREAKPOINT:
5876    case OP_DISPATCH_FF:
5877    case OP_UNUSED_27FF:
5878    case OP_UNUSED_28FF:
5879    case OP_UNUSED_29FF:
5880    case OP_UNUSED_2AFF:
5881    case OP_UNUSED_2BFF:
5882    case OP_UNUSED_2CFF:
5883    case OP_UNUSED_2DFF:
5884    case OP_UNUSED_2EFF:
5885    case OP_UNUSED_2FFF:
5886    case OP_UNUSED_30FF:
5887    case OP_UNUSED_31FF:
5888    case OP_UNUSED_32FF:
5889    case OP_UNUSED_33FF:
5890    case OP_UNUSED_34FF:
5891    case OP_UNUSED_35FF:
5892    case OP_UNUSED_36FF:
5893    case OP_UNUSED_37FF:
5894    case OP_UNUSED_38FF:
5895    case OP_UNUSED_39FF:
5896    case OP_UNUSED_3AFF:
5897    case OP_UNUSED_3BFF:
5898    case OP_UNUSED_3CFF:
5899    case OP_UNUSED_3DFF:
5900    case OP_UNUSED_3EFF:
5901    case OP_UNUSED_3FFF:
5902    case OP_UNUSED_40FF:
5903    case OP_UNUSED_41FF:
5904    case OP_UNUSED_42FF:
5905    case OP_UNUSED_43FF:
5906    case OP_UNUSED_44FF:
5907    case OP_UNUSED_45FF:
5908    case OP_UNUSED_46FF:
5909    case OP_UNUSED_47FF:
5910    case OP_UNUSED_48FF:
5911    case OP_UNUSED_49FF:
5912    case OP_UNUSED_4AFF:
5913    case OP_UNUSED_4BFF:
5914    case OP_UNUSED_4CFF:
5915    case OP_UNUSED_4DFF:
5916    case OP_UNUSED_4EFF:
5917    case OP_UNUSED_4FFF:
5918    case OP_UNUSED_50FF:
5919    case OP_UNUSED_51FF:
5920    case OP_UNUSED_52FF:
5921    case OP_UNUSED_53FF:
5922    case OP_UNUSED_54FF:
5923    case OP_UNUSED_55FF:
5924    case OP_UNUSED_56FF:
5925    case OP_UNUSED_57FF:
5926    case OP_UNUSED_58FF:
5927    case OP_UNUSED_59FF:
5928    case OP_UNUSED_5AFF:
5929    case OP_UNUSED_5BFF:
5930    case OP_UNUSED_5CFF:
5931    case OP_UNUSED_5DFF:
5932    case OP_UNUSED_5EFF:
5933    case OP_UNUSED_5FFF:
5934    case OP_UNUSED_60FF:
5935    case OP_UNUSED_61FF:
5936    case OP_UNUSED_62FF:
5937    case OP_UNUSED_63FF:
5938    case OP_UNUSED_64FF:
5939    case OP_UNUSED_65FF:
5940    case OP_UNUSED_66FF:
5941    case OP_UNUSED_67FF:
5942    case OP_UNUSED_68FF:
5943    case OP_UNUSED_69FF:
5944    case OP_UNUSED_6AFF:
5945    case OP_UNUSED_6BFF:
5946    case OP_UNUSED_6CFF:
5947    case OP_UNUSED_6DFF:
5948    case OP_UNUSED_6EFF:
5949    case OP_UNUSED_6FFF:
5950    case OP_UNUSED_70FF:
5951    case OP_UNUSED_71FF:
5952    case OP_UNUSED_72FF:
5953    case OP_UNUSED_73FF:
5954    case OP_UNUSED_74FF:
5955    case OP_UNUSED_75FF:
5956    case OP_UNUSED_76FF:
5957    case OP_UNUSED_77FF:
5958    case OP_UNUSED_78FF:
5959    case OP_UNUSED_79FF:
5960    case OP_UNUSED_7AFF:
5961    case OP_UNUSED_7BFF:
5962    case OP_UNUSED_7CFF:
5963    case OP_UNUSED_7DFF:
5964    case OP_UNUSED_7EFF:
5965    case OP_UNUSED_7FFF:
5966    case OP_UNUSED_80FF:
5967    case OP_UNUSED_81FF:
5968    case OP_UNUSED_82FF:
5969    case OP_UNUSED_83FF:
5970    case OP_UNUSED_84FF:
5971    case OP_UNUSED_85FF:
5972    case OP_UNUSED_86FF:
5973    case OP_UNUSED_87FF:
5974    case OP_UNUSED_88FF:
5975    case OP_UNUSED_89FF:
5976    case OP_UNUSED_8AFF:
5977    case OP_UNUSED_8BFF:
5978    case OP_UNUSED_8CFF:
5979    case OP_UNUSED_8DFF:
5980    case OP_UNUSED_8EFF:
5981    case OP_UNUSED_8FFF:
5982    case OP_UNUSED_90FF:
5983    case OP_UNUSED_91FF:
5984    case OP_UNUSED_92FF:
5985    case OP_UNUSED_93FF:
5986    case OP_UNUSED_94FF:
5987    case OP_UNUSED_95FF:
5988    case OP_UNUSED_96FF:
5989    case OP_UNUSED_97FF:
5990    case OP_UNUSED_98FF:
5991    case OP_UNUSED_99FF:
5992    case OP_UNUSED_9AFF:
5993    case OP_UNUSED_9BFF:
5994    case OP_UNUSED_9CFF:
5995    case OP_UNUSED_9DFF:
5996    case OP_UNUSED_9EFF:
5997    case OP_UNUSED_9FFF:
5998    case OP_UNUSED_A0FF:
5999    case OP_UNUSED_A1FF:
6000    case OP_UNUSED_A2FF:
6001    case OP_UNUSED_A3FF:
6002    case OP_UNUSED_A4FF:
6003    case OP_UNUSED_A5FF:
6004    case OP_UNUSED_A6FF:
6005    case OP_UNUSED_A7FF:
6006    case OP_UNUSED_A8FF:
6007    case OP_UNUSED_A9FF:
6008    case OP_UNUSED_AAFF:
6009    case OP_UNUSED_ABFF:
6010    case OP_UNUSED_ACFF:
6011    case OP_UNUSED_ADFF:
6012    case OP_UNUSED_AEFF:
6013    case OP_UNUSED_AFFF:
6014    case OP_UNUSED_B0FF:
6015    case OP_UNUSED_B1FF:
6016    case OP_UNUSED_B2FF:
6017    case OP_UNUSED_B3FF:
6018    case OP_UNUSED_B4FF:
6019    case OP_UNUSED_B5FF:
6020    case OP_UNUSED_B6FF:
6021    case OP_UNUSED_B7FF:
6022    case OP_UNUSED_B8FF:
6023    case OP_UNUSED_B9FF:
6024    case OP_UNUSED_BAFF:
6025    case OP_UNUSED_BBFF:
6026    case OP_UNUSED_BCFF:
6027    case OP_UNUSED_BDFF:
6028    case OP_UNUSED_BEFF:
6029    case OP_UNUSED_BFFF:
6030    case OP_UNUSED_C0FF:
6031    case OP_UNUSED_C1FF:
6032    case OP_UNUSED_C2FF:
6033    case OP_UNUSED_C3FF:
6034    case OP_UNUSED_C4FF:
6035    case OP_UNUSED_C5FF:
6036    case OP_UNUSED_C6FF:
6037    case OP_UNUSED_C7FF:
6038    case OP_UNUSED_C8FF:
6039    case OP_UNUSED_C9FF:
6040    case OP_UNUSED_CAFF:
6041    case OP_UNUSED_CBFF:
6042    case OP_UNUSED_CCFF:
6043    case OP_UNUSED_CDFF:
6044    case OP_UNUSED_CEFF:
6045    case OP_UNUSED_CFFF:
6046    case OP_UNUSED_D0FF:
6047    case OP_UNUSED_D1FF:
6048    case OP_UNUSED_D2FF:
6049    case OP_UNUSED_D3FF:
6050    case OP_UNUSED_D4FF:
6051    case OP_UNUSED_D5FF:
6052    case OP_UNUSED_D6FF:
6053    case OP_UNUSED_D7FF:
6054    case OP_UNUSED_D8FF:
6055    case OP_UNUSED_D9FF:
6056    case OP_UNUSED_DAFF:
6057    case OP_UNUSED_DBFF:
6058    case OP_UNUSED_DCFF:
6059    case OP_UNUSED_DDFF:
6060    case OP_UNUSED_DEFF:
6061    case OP_UNUSED_DFFF:
6062    case OP_UNUSED_E0FF:
6063    case OP_UNUSED_E1FF:
6064    case OP_UNUSED_E2FF:
6065    case OP_UNUSED_E3FF:
6066    case OP_UNUSED_E4FF:
6067    case OP_UNUSED_E5FF:
6068    case OP_UNUSED_E6FF:
6069    case OP_UNUSED_E7FF:
6070    case OP_UNUSED_E8FF:
6071    case OP_UNUSED_E9FF:
6072    case OP_UNUSED_EAFF:
6073    case OP_UNUSED_EBFF:
6074    case OP_UNUSED_ECFF:
6075    case OP_UNUSED_EDFF:
6076    case OP_UNUSED_EEFF:
6077    case OP_UNUSED_EFFF:
6078    case OP_UNUSED_F0FF:
6079    case OP_UNUSED_F1FF:
6080        failure = VERIFY_ERROR_GENERIC;
6081        break;
6082
6083    /*
6084     * DO NOT add a "default" clause here.  Without it the compiler will
6085     * complain if an instruction is missing (which is desirable).
6086     */
6087    }
6088
6089    if (!VERIFY_OK(failure)) {
6090        if (failure == VERIFY_ERROR_GENERIC || gDvm.optimizing) {
6091            /* immediate failure, reject class */
6092            LOG_VFY_METH(meth, "VFY:  rejecting opcode 0x%02x at 0x%04x",
6093                decInsn.opcode, insnIdx);
6094            goto bail;
6095        } else {
6096            /* replace opcode and continue on */
6097            LOGD("VFY: replacing opcode 0x%02x at 0x%04x",
6098                decInsn.opcode, insnIdx);
6099            if (!replaceFailingInstruction(meth, insnFlags, insnIdx, failure)) {
6100                LOG_VFY_METH(meth, "VFY:  rejecting opcode 0x%02x at 0x%04x",
6101                    decInsn.opcode, insnIdx);
6102                goto bail;
6103            }
6104            /* IMPORTANT: meth->insns may have been changed */
6105            insns = meth->insns + insnIdx;
6106
6107            /* continue on as if we just handled a throw-verification-error */
6108            failure = VERIFY_ERROR_NONE;
6109            nextFlags = kInstrCanThrow;
6110        }
6111    }
6112
6113    /*
6114     * If we didn't just set the result register, clear it out.  This
6115     * ensures that you can only use "move-result" immediately after the
6116     * result is set.  (We could check this statically, but it's not
6117     * expensive and it makes our debugging output cleaner.)
6118     */
6119    if (!justSetResult) {
6120        int reg = RESULT_REGISTER(insnRegCount);
6121        setRegisterType(workLine, reg, kRegTypeUnknown);
6122        setRegisterType(workLine, reg+1, kRegTypeUnknown);
6123    }
6124
6125    /*
6126     * Handle "continue".  Tag the next consecutive instruction.
6127     */
6128    if ((nextFlags & kInstrCanContinue) != 0) {
6129        int insnWidth = dvmInsnGetWidth(insnFlags, insnIdx);
6130        if (insnIdx+insnWidth >= insnsSize) {
6131            LOG_VFY_METH(meth,
6132                "VFY: execution can walk off end of code area (from %#x)",
6133                insnIdx);
6134            goto bail;
6135        }
6136
6137        /*
6138         * The only way to get to a move-exception instruction is to get
6139         * thrown there.  Make sure the next instruction isn't one.
6140         */
6141        if (!checkMoveException(meth, insnIdx+insnWidth, "next"))
6142            goto bail;
6143
6144        if (getRegisterLine(regTable, insnIdx+insnWidth)->regTypes != NULL) {
6145            /*
6146             * Merge registers into what we have for the next instruction,
6147             * and set the "changed" flag if needed.
6148             */
6149            if (!updateRegisters(meth, insnFlags, regTable, insnIdx+insnWidth,
6150                    workLine))
6151                goto bail;
6152        } else {
6153            /*
6154             * We're not recording register data for the next instruction,
6155             * so we don't know what the prior state was.  We have to
6156             * assume that something has changed and re-evaluate it.
6157             */
6158            dvmInsnSetChanged(insnFlags, insnIdx+insnWidth, true);
6159        }
6160    }
6161
6162    /*
6163     * Handle "branch".  Tag the branch target.
6164     *
6165     * NOTE: instructions like OP_EQZ provide information about the state
6166     * of the register when the branch is taken or not taken.  For example,
6167     * somebody could get a reference field, check it for zero, and if the
6168     * branch is taken immediately store that register in a boolean field
6169     * since the value is known to be zero.  We do not currently account for
6170     * that, and will reject the code.
6171     *
6172     * TODO: avoid re-fetching the branch target
6173     */
6174    if ((nextFlags & kInstrCanBranch) != 0) {
6175        bool isConditional;
6176
6177        if (!dvmGetBranchOffset(meth, insnFlags, insnIdx, &branchTarget,
6178                &isConditional))
6179        {
6180            /* should never happen after static verification */
6181            LOG_VFY_METH(meth, "VFY: bad branch at %d", insnIdx);
6182            goto bail;
6183        }
6184        assert(isConditional || (nextFlags & kInstrCanContinue) == 0);
6185        assert(!isConditional || (nextFlags & kInstrCanContinue) != 0);
6186
6187        if (!checkMoveException(meth, insnIdx+branchTarget, "branch"))
6188            goto bail;
6189
6190        /* update branch target, set "changed" if appropriate */
6191        if (!updateRegisters(meth, insnFlags, regTable, insnIdx+branchTarget,
6192                workLine))
6193            goto bail;
6194    }
6195
6196    /*
6197     * Handle "switch".  Tag all possible branch targets.
6198     *
6199     * We've already verified that the table is structurally sound, so we
6200     * just need to walk through and tag the targets.
6201     */
6202    if ((nextFlags & kInstrCanSwitch) != 0) {
6203        int offsetToSwitch = insns[1] | (((s4)insns[2]) << 16);
6204        const u2* switchInsns = insns + offsetToSwitch;
6205        int switchCount = switchInsns[1];
6206        int offsetToTargets, targ;
6207
6208        if ((*insns & 0xff) == OP_PACKED_SWITCH) {
6209            /* 0=sig, 1=count, 2/3=firstKey */
6210            offsetToTargets = 4;
6211        } else {
6212            /* 0=sig, 1=count, 2..count*2 = keys */
6213            assert((*insns & 0xff) == OP_SPARSE_SWITCH);
6214            offsetToTargets = 2 + 2*switchCount;
6215        }
6216
6217        /* verify each switch target */
6218        for (targ = 0; targ < switchCount; targ++) {
6219            int offset, absOffset;
6220
6221            /* offsets are 32-bit, and only partly endian-swapped */
6222            offset = switchInsns[offsetToTargets + targ*2] |
6223                     (((s4) switchInsns[offsetToTargets + targ*2 +1]) << 16);
6224            absOffset = insnIdx + offset;
6225
6226            assert(absOffset >= 0 && absOffset < insnsSize);
6227
6228            if (!checkMoveException(meth, absOffset, "switch"))
6229                goto bail;
6230
6231            if (!updateRegisters(meth, insnFlags, regTable, absOffset,
6232                    workLine))
6233                goto bail;
6234        }
6235    }
6236
6237    /*
6238     * Handle instructions that can throw and that are sitting in a
6239     * "try" block.  (If they're not in a "try" block when they throw,
6240     * control transfers out of the method.)
6241     */
6242    if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
6243    {
6244        const DexCode* pCode = dvmGetMethodCode(meth);
6245        DexCatchIterator iterator;
6246        bool hasCatchAll = false;
6247
6248        if (dexFindCatchHandler(&iterator, pCode, insnIdx)) {
6249            for (;;) {
6250                DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
6251
6252                if (handler == NULL) {
6253                    break;
6254                }
6255
6256                if (handler->typeIdx == kDexNoIndex)
6257                    hasCatchAll = true;
6258
6259                /*
6260                 * Merge registers into the "catch" block.  We want to
6261                 * use the "savedRegs" rather than "workRegs", because
6262                 * at runtime the exception will be thrown before the
6263                 * instruction modifies any registers.
6264                 */
6265                if (!updateRegisters(meth, insnFlags, regTable,
6266                        handler->address, &regTable->savedLine))
6267                    goto bail;
6268            }
6269        }
6270
6271        /*
6272         * If the monitor stack depth is nonzero, there must be a "catch all"
6273         * handler for this instruction.  This does apply to monitor-exit
6274         * because of async exception handling.
6275         */
6276        if (workLine->monitorStackTop != 0 && !hasCatchAll) {
6277            /*
6278             * The state in workLine reflects the post-execution state.
6279             * If the current instruction is a monitor-enter and the monitor
6280             * stack was empty, we don't need a catch-all (if it throws,
6281             * it will do so before grabbing the lock).
6282             */
6283            if (!(decInsn.opcode == OP_MONITOR_ENTER &&
6284                  workLine->monitorStackTop == 1))
6285            {
6286                LOG_VFY_METH(meth,
6287                    "VFY: no catch-all for instruction at 0x%04x", insnIdx);
6288                goto bail;
6289            }
6290        }
6291    }
6292
6293    /*
6294     * If we're returning from the method, make sure our monitor stack
6295     * is empty.
6296     */
6297    if ((nextFlags & kInstrCanReturn) != 0 && workLine->monitorStackTop != 0) {
6298        LOG_VFY_METH(meth, "VFY: return with stack depth=%d at 0x%04x",
6299            workLine->monitorStackTop, insnIdx);
6300        goto bail;
6301    }
6302
6303    /*
6304     * Update startGuess.  Advance to the next instruction of that's
6305     * possible, otherwise use the branch target if one was found.  If
6306     * neither of those exists we're in a return or throw; leave startGuess
6307     * alone and let the caller sort it out.
6308     */
6309    if ((nextFlags & kInstrCanContinue) != 0) {
6310        *pStartGuess = insnIdx + dvmInsnGetWidth(insnFlags, insnIdx);
6311    } else if ((nextFlags & kInstrCanBranch) != 0) {
6312        /* we're still okay if branchTarget is zero */
6313        *pStartGuess = insnIdx + branchTarget;
6314    }
6315
6316    assert(*pStartGuess >= 0 && *pStartGuess < insnsSize &&
6317        dvmInsnGetWidth(insnFlags, *pStartGuess) != 0);
6318
6319    result = true;
6320
6321bail:
6322    return result;
6323}
6324
6325
6326/*
6327 * callback function used in dumpRegTypes to print local vars
6328 * valid at a given address.
6329 */
6330static void logLocalsCb(void *cnxt, u2 reg, u4 startAddress, u4 endAddress,
6331        const char *name, const char *descriptor,
6332        const char *signature)
6333{
6334    int addr = *((int *)cnxt);
6335
6336    if (addr >= (int) startAddress && addr < (int) endAddress)
6337    {
6338        LOGI("        %2d: '%s' %s", reg, name, descriptor);
6339    }
6340}
6341
6342/*
6343 * Dump the register types for the specifed address to the log file.
6344 */
6345static void dumpRegTypes(const VerifierData* vdata,
6346    const RegisterLine* registerLine, int addr, const char* addrName,
6347    const UninitInstanceMap* uninitMap, int displayFlags)
6348{
6349    const Method* meth = vdata->method;
6350    const InsnFlags* insnFlags = vdata->insnFlags;
6351    const RegType* addrRegs = registerLine->regTypes;
6352    int regCount = meth->registersSize;
6353    int fullRegCount = regCount + kExtraRegs;
6354    bool branchTarget = dvmInsnIsBranchTarget(insnFlags, addr);
6355    int i;
6356
6357    assert(addr >= 0 && addr < (int) dvmGetMethodInsnsSize(meth));
6358
6359    int regCharSize = fullRegCount + (fullRegCount-1)/4 + 2 +1;
6360    char regChars[regCharSize +1];
6361    memset(regChars, ' ', regCharSize);
6362    regChars[0] = '[';
6363    if (regCount == 0)
6364        regChars[1] = ']';
6365    else
6366        regChars[1 + (regCount-1) + (regCount-1)/4 +1] = ']';
6367    regChars[regCharSize] = '\0';
6368
6369    for (i = 0; i < regCount + kExtraRegs; i++) {
6370        char tch;
6371
6372        switch (addrRegs[i]) {
6373        case kRegTypeUnknown:       tch = '.';  break;
6374        case kRegTypeConflict:      tch = 'X';  break;
6375        case kRegTypeZero:          tch = '0';  break;
6376        case kRegTypeOne:           tch = '1';  break;
6377        case kRegTypeBoolean:       tch = 'Z';  break;
6378        case kRegTypeConstPosByte:  tch = 'y';  break;
6379        case kRegTypeConstByte:     tch = 'Y';  break;
6380        case kRegTypeConstPosShort: tch = 'h';  break;
6381        case kRegTypeConstShort:    tch = 'H';  break;
6382        case kRegTypeConstChar:     tch = 'c';  break;
6383        case kRegTypeConstInteger:  tch = 'i';  break;
6384        case kRegTypePosByte:       tch = 'b';  break;
6385        case kRegTypeByte:          tch = 'B';  break;
6386        case kRegTypePosShort:      tch = 's';  break;
6387        case kRegTypeShort:         tch = 'S';  break;
6388        case kRegTypeChar:          tch = 'C';  break;
6389        case kRegTypeInteger:       tch = 'I';  break;
6390        case kRegTypeFloat:         tch = 'F';  break;
6391        case kRegTypeConstLo:       tch = 'N';  break;
6392        case kRegTypeConstHi:       tch = 'n';  break;
6393        case kRegTypeLongLo:        tch = 'J';  break;
6394        case kRegTypeLongHi:        tch = 'j';  break;
6395        case kRegTypeDoubleLo:      tch = 'D';  break;
6396        case kRegTypeDoubleHi:      tch = 'd';  break;
6397        default:
6398            if (regTypeIsReference(addrRegs[i])) {
6399                if (regTypeIsUninitReference(addrRegs[i]))
6400                    tch = 'U';
6401                else
6402                    tch = 'L';
6403            } else {
6404                tch = '*';
6405                assert(false);
6406            }
6407            break;
6408        }
6409
6410        if (i < regCount)
6411            regChars[1 + i + (i/4)] = tch;
6412        else
6413            regChars[1 + i + (i/4) + 2] = tch;
6414    }
6415
6416    if (addr == 0 && addrName != NULL) {
6417        LOGI("%c%s %s mst=%d", branchTarget ? '>' : ' ',
6418            addrName, regChars, registerLine->monitorStackTop);
6419    } else {
6420        LOGI("%c0x%04x %s mst=%d", branchTarget ? '>' : ' ',
6421            addr, regChars, registerLine->monitorStackTop);
6422    }
6423    if (displayFlags & DRT_SHOW_LIVENESS) {
6424        /*
6425         * We can't use registerLine->liveRegs because it might be the
6426         * "work line" rather than the copy from RegisterTable.
6427         */
6428        BitVector* liveRegs = vdata->registerLines[addr].liveRegs;
6429        if (liveRegs != NULL)  {
6430            char liveChars[regCharSize + 1];
6431            memset(liveChars, ' ', regCharSize);
6432            liveChars[regCharSize] = '\0';
6433
6434            for (i = 0; i < regCount; i++) {
6435                bool isLive = dvmIsBitSet(liveRegs, i);
6436                liveChars[i + 1 + (i / 4)] = isLive ? '+' : '-';
6437            }
6438            LOGI("        %s", liveChars);
6439        } else {
6440            LOGI("        %c", '#');
6441        }
6442    }
6443
6444    if (displayFlags & DRT_SHOW_REF_TYPES) {
6445        for (i = 0; i < regCount + kExtraRegs; i++) {
6446            if (regTypeIsReference(addrRegs[i]) && addrRegs[i] != kRegTypeZero)
6447            {
6448                ClassObject* clazz = regTypeReferenceToClass(addrRegs[i], uninitMap);
6449                assert(dvmIsHeapAddress((Object*)clazz));
6450                if (i < regCount) {
6451                    LOGI("        %2d: 0x%08x %s%s",
6452                        i, addrRegs[i],
6453                        regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "",
6454                        clazz->descriptor);
6455                } else {
6456                    LOGI("        RS: 0x%08x %s%s",
6457                        addrRegs[i],
6458                        regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "",
6459                        clazz->descriptor);
6460                }
6461            }
6462        }
6463    }
6464    if (displayFlags & DRT_SHOW_LOCALS) {
6465        dexDecodeDebugInfo(meth->clazz->pDvmDex->pDexFile,
6466                dvmGetMethodCode(meth),
6467                meth->clazz->descriptor,
6468                meth->prototype.protoIdx,
6469                meth->accessFlags,
6470                NULL, logLocalsCb, &addr);
6471    }
6472}
6473