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