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