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