2 * Copyright (C) 2008 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 * Dalvik bytecode structural verifier. The only public entry point
19 * (except for a few shared utility functions) is dvmVerifyCodeFlow().
21 * TODO: might benefit from a signature-->class lookup cache. Could avoid
22 * some string-peeling and wouldn't need to compute hashes.
24 * TODO: we do too much stuff in here that could be done in the static
25 * verification pass. It's convenient, because we have all of the
26 * necessary information, but it's more efficient to do it over in
27 * DexVerify.c because in here we may have to process instructions
31 #include "analysis/CodeVerify.h"
32 #include "analysis/Optimize.h"
33 #include "analysis/RegisterMap.h"
34 #include "libdex/DexCatch.h"
35 #include "libdex/InstrUtils.h"
41 * We don't need to store the register data for many instructions, because
42 * we either only need it at branch points (for verification) or GC points
43 * and branches (for verification + type-precise register analysis).
45 typedef enum RegisterTrackingMode {
49 } RegisterTrackingMode;
52 * Set this to enable dead code scanning. This is not required, but it's
53 * very useful when testing changes to the verifier (to make sure we're not
54 * skipping over stuff) and for checking the optimized output from "dx".
55 * The only reason not to do it is that it slightly increases the time
56 * required to perform verification.
58 #define DEAD_CODE_SCAN true
60 static bool gDebugVerbose = false; // TODO: remove this
63 int gDvm__totalInstr = 0;
64 int gDvm__gcInstr = 0;
66 int gDvm__gcSimpleData = 0;
70 * Selectively enable verbose debug logging -- use this to activate
71 * dumpRegTypes() calls for all instructions in the specified method.
73 static inline bool doVerboseLogging(const Method* meth) {
74 return false; /* COMMENT OUT to enable verbose debugging */
76 const char* cd = "Landroid/net/http/Request;";
77 const char* mn = "readResponse";
78 const char* sg = "(Landroid/net/http/AndroidHttpClientConnection;)V";
79 return (strcmp(meth->clazz->descriptor, cd) == 0 &&
80 dvmCompareNameDescriptorAndMethod(mn, sg, meth) == 0);
83 #define SHOW_REG_DETAILS (0 /*| DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS*/)
86 * We need an extra "pseudo register" to hold the return type briefly. It
87 * can be category 1 or 2, so we need two slots.
90 #define RESULT_REGISTER(_insnRegCount) (_insnRegCount)
93 * Big fat collection of registers.
95 typedef struct RegisterTable {
97 * Array of RegType arrays, one per address in the method. We only
98 * set the pointers for certain addresses, based on what we're trying
104 * Number of registers we track for each instruction. This is equal
105 * to the method's declared "registersSize" plus kExtraRegs.
107 int insnRegCountPlus;
110 * A single large alloc, with all of the storage needed for addrRegs.
118 static void checkMergeTab(void);
120 static bool isInitMethod(const Method* meth);
121 static RegType getInvocationThis(const RegType* insnRegs,\
122 const int insnRegCount, const DecodedInstruction* pDecInsn,
123 VerifyError* pFailure);
124 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,\
125 u4 vsrc, RegType checkType, VerifyError* pFailure);
126 static bool doCodeVerification(const Method* meth, InsnFlags* insnFlags,\
127 RegisterTable* regTable, UninitInstanceMap* uninitMap);
128 static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,\
129 RegisterTable* regTable, RegType* workRegs, int insnIdx,
130 UninitInstanceMap* uninitMap, int* pStartGuess);
131 static ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2);
132 static void dumpRegTypes(const Method* meth, const InsnFlags* insnFlags,\
133 const RegType* addrRegs, int addr, const char* addrName,
134 const UninitInstanceMap* uninitMap, int displayFlags);
136 /* bit values for dumpRegTypes() "displayFlags" */
139 DRT_SHOW_REF_TYPES = 0x01,
140 DRT_SHOW_LOCALS = 0x02,
145 * ===========================================================================
146 * RegType and UninitInstanceMap utility functions
147 * ===========================================================================
150 #define __ kRegTypeUnknown
151 #define _U kRegTypeUninit
152 #define _X kRegTypeConflict
153 #define _F kRegTypeFloat
154 #define _0 kRegTypeZero
155 #define _1 kRegTypeOne
156 #define _Z kRegTypeBoolean
157 #define _b kRegTypePosByte
158 #define _B kRegTypeByte
159 #define _s kRegTypePosShort
160 #define _S kRegTypeShort
161 #define _C kRegTypeChar
162 #define _I kRegTypeInteger
163 #define _J kRegTypeLongLo
164 #define _j kRegTypeLongHi
165 #define _D kRegTypeDoubleLo
166 #define _d kRegTypeDoubleHi
169 * Merge result table for primitive values. The table is symmetric along
172 * Note that 32-bit int/float do not merge into 64-bit long/double. This
173 * is a register merge, not a widening conversion. Only the "implicit"
174 * widening within a category, e.g. byte to short, is allowed.
176 * Because Dalvik does not draw a distinction between int and float, we
177 * have to allow free exchange between 32-bit int/float and 64-bit
180 * Note that Uninit+Uninit=Uninit. This holds true because we only
181 * use this when the RegType value is exactly equal to kRegTypeUninit, which
182 * can only happen for the zeroeth entry in the table.
184 * "Unknown" never merges with anything known. The only time a register
185 * transitions from "unknown" to "known" is when we're executing code
186 * for the first time, and we handle that with a simple copy.
188 const char gDvmMergeTab[kRegTypeMAX][kRegTypeMAX] =
190 /* chk: _ U X F 0 1 Z b B s S C I J j D d */
191 { /*_*/ __,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X },
192 { /*U*/ _X,_U,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X },
193 { /*X*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X },
194 { /*F*/ _X,_X,_X,_F,_F,_F,_F,_F,_F,_F,_F,_F,_F,_X,_X,_X,_X },
195 { /*0*/ _X,_X,_X,_F,_0,_Z,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
196 { /*1*/ _X,_X,_X,_F,_Z,_1,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
197 { /*Z*/ _X,_X,_X,_F,_Z,_Z,_Z,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
198 { /*b*/ _X,_X,_X,_F,_b,_b,_b,_b,_B,_s,_S,_C,_I,_X,_X,_X,_X },
199 { /*B*/ _X,_X,_X,_F,_B,_B,_B,_B,_B,_S,_S,_I,_I,_X,_X,_X,_X },
200 { /*s*/ _X,_X,_X,_F,_s,_s,_s,_s,_S,_s,_S,_C,_I,_X,_X,_X,_X },
201 { /*S*/ _X,_X,_X,_F,_S,_S,_S,_S,_S,_S,_S,_I,_I,_X,_X,_X,_X },
202 { /*C*/ _X,_X,_X,_F,_C,_C,_C,_C,_I,_C,_I,_C,_I,_X,_X,_X,_X },
203 { /*I*/ _X,_X,_X,_F,_I,_I,_I,_I,_I,_I,_I,_I,_I,_X,_X,_X,_X },
204 { /*J*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_J,_X,_J,_X },
205 { /*j*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_j,_X,_j },
206 { /*D*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_J,_X,_D,_X },
207 { /*d*/ _X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_X,_j,_X,_d },
230 * Verify symmetry in the conversion table.
232 static void checkMergeTab(void)
236 for (i = 0; i < kRegTypeMAX; i++) {
237 for (j = i; j < kRegTypeMAX; j++) {
238 if (gDvmMergeTab[i][j] != gDvmMergeTab[j][i]) {
239 LOGE("Symmetry violation: %d,%d vs %d,%d\n", i, j, j, i);
248 * Determine whether we can convert "srcType" to "checkType", where
249 * "checkType" is one of the category-1 non-reference types.
251 * 32-bit int and float are interchangeable.
253 static bool canConvertTo1nr(RegType srcType, RegType checkType)
255 static const char convTab
256 [kRegType1nrEND-kRegType1nrSTART+1][kRegType1nrEND-kRegType1nrSTART+1] =
258 /* chk: F 0 1 Z b B s S C I */
259 { /*F*/ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
260 { /*0*/ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1 },
261 { /*1*/ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
262 { /*Z*/ 1, 0, 0, 1, 1, 1, 1, 1, 1, 1 },
263 { /*b*/ 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 },
264 { /*B*/ 1, 0, 0, 0, 0, 1, 0, 1, 0, 1 },
265 { /*s*/ 1, 0, 0, 0, 0, 0, 1, 1, 1, 1 },
266 { /*S*/ 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 },
267 { /*C*/ 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
268 { /*I*/ 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
271 assert(checkType >= kRegType1nrSTART && checkType <= kRegType1nrEND);
273 if (checkType < kRegType1nrSTART || checkType > kRegType1nrEND) {
274 LOG_VFY("Unexpected checkType %d (srcType=%d)\n", checkType, srcType);
280 //printf("convTab[%d][%d] = %d\n", srcType, checkType,
281 // convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART]);
282 if (srcType >= kRegType1nrSTART && srcType <= kRegType1nrEND)
283 return (bool) convTab[srcType-kRegType1nrSTART][checkType-kRegType1nrSTART];
289 * Determine whether the types are compatible. In Dalvik, 64-bit doubles
290 * and longs are interchangeable.
292 static bool canConvertTo2(RegType srcType, RegType checkType)
294 return ((srcType == kRegTypeLongLo || srcType == kRegTypeDoubleLo) &&
295 (checkType == kRegTypeLongLo || checkType == kRegTypeDoubleLo));
299 * Determine whether or not "instrType" and "targetType" are compatible,
300 * for purposes of getting or setting a value in a field or array. The
301 * idea is that an instruction with a category 1nr type (say, aget-short
302 * or iput-boolean) is accessing a static field, instance field, or array
303 * entry, and we want to make sure sure that the operation is legal.
305 * At a minimum, source and destination must have the same width. We
306 * further refine this to assert that "short" and "char" are not
307 * compatible, because the sign-extension is different on the "get"
308 * operations. As usual, "float" and "int" are interoperable.
310 * We're not considering the actual contents of the register, so we'll
311 * never get "pseudo-types" like kRegTypeZero or kRegTypePosShort. We
312 * could get kRegTypeUnknown in "targetType" if a field or array class
313 * lookup failed. Category 2 types and references are checked elsewhere.
315 static bool checkFieldArrayStore1nr(RegType instrType, RegType targetType)
317 if (instrType == targetType)
318 return true; /* quick positive; most common case */
320 if ((instrType == kRegTypeInteger && targetType == kRegTypeFloat) ||
321 (instrType == kRegTypeFloat && targetType == kRegTypeInteger))
330 * Convert a VM PrimitiveType enum value to the equivalent RegType value.
332 static RegType primitiveTypeToRegType(PrimitiveType primType)
334 static const struct {
335 RegType regType; /* type equivalent */
336 PrimitiveType primType; /* verification */
338 /* must match order of enum in Object.h */
339 { kRegTypeBoolean, PRIM_BOOLEAN },
340 { kRegTypeChar, PRIM_CHAR },
341 { kRegTypeFloat, PRIM_FLOAT },
342 { kRegTypeDoubleLo, PRIM_DOUBLE },
343 { kRegTypeByte, PRIM_BYTE },
344 { kRegTypeShort, PRIM_SHORT },
345 { kRegTypeInteger, PRIM_INT },
346 { kRegTypeLongLo, PRIM_LONG },
350 if (primType < 0 || primType > (int) (sizeof(convTab) / sizeof(convTab[0])))
353 return kRegTypeUnknown;
356 assert(convTab[primType].primType == primType);
357 return convTab[primType].regType;
361 * Create a new uninitialized instance map.
363 * The map is allocated and populated with address entries. The addresses
364 * appear in ascending order to allow binary searching.
366 * Very few methods have 10 or more new-instance instructions; the
367 * majority have 0 or 1. Occasionally a static initializer will have 200+.
369 UninitInstanceMap* dvmCreateUninitInstanceMap(const Method* meth,
370 const InsnFlags* insnFlags, int newInstanceCount)
372 const int insnsSize = dvmGetMethodInsnsSize(meth);
373 const u2* insns = meth->insns;
374 UninitInstanceMap* uninitMap;
378 if (isInitMethod(meth)) {
384 * Allocate the header and map as a single unit.
386 * TODO: consider having a static instance so we can avoid allocations.
387 * I don't think the verifier is guaranteed to be single-threaded when
388 * running in the VM (rather than dexopt), so that must be taken into
391 int size = offsetof(UninitInstanceMap, map) +
392 newInstanceCount * sizeof(uninitMap->map[0]);
393 uninitMap = calloc(1, size);
394 if (uninitMap == NULL)
396 uninitMap->numEntries = newInstanceCount;
400 uninitMap->map[idx++].addr = kUninitThisArgAddr;
404 * Run through and find the new-instance instructions.
406 for (addr = 0; addr < insnsSize; /**/) {
407 int width = dvmInsnGetWidth(insnFlags, addr);
409 if ((*insns & 0xff) == OP_NEW_INSTANCE)
410 uninitMap->map[idx++].addr = addr;
416 assert(idx == newInstanceCount);
423 void dvmFreeUninitInstanceMap(UninitInstanceMap* uninitMap)
429 * Set the class object associated with the instruction at "addr".
431 * Returns the map slot index, or -1 if the address isn't listed in the map
432 * (shouldn't happen) or if a class is already associated with the address
435 * Entries, once set, do not change -- a given address can only allocate
436 * one type of object.
438 int dvmSetUninitInstance(UninitInstanceMap* uninitMap, int addr,
443 assert(clazz != NULL);
445 /* TODO: binary search when numEntries > 8 */
446 for (idx = uninitMap->numEntries - 1; idx >= 0; idx--) {
447 if (uninitMap->map[idx].addr == addr) {
448 if (uninitMap->map[idx].clazz != NULL &&
449 uninitMap->map[idx].clazz != clazz)
451 LOG_VFY("VFY: addr %d already set to %p, not setting to %p\n",
452 addr, uninitMap->map[idx].clazz, clazz);
453 return -1; // already set to something else??
455 uninitMap->map[idx].clazz = clazz;
460 LOG_VFY("VFY: addr %d not found in uninit map\n", addr);
461 assert(false); // shouldn't happen
466 * Get the class object at the specified index.
468 ClassObject* dvmGetUninitInstance(const UninitInstanceMap* uninitMap, int idx)
470 assert(idx >= 0 && idx < uninitMap->numEntries);
471 return uninitMap->map[idx].clazz;
474 /* determine if "type" is actually an object reference (init/uninit/zero) */
475 static inline bool regTypeIsReference(RegType type) {
476 return (type > kRegTypeMAX || type == kRegTypeUninit ||
477 type == kRegTypeZero);
480 /* determine if "type" is an uninitialized object reference */
481 static inline bool regTypeIsUninitReference(RegType type) {
482 return ((type & kRegTypeUninitMask) == kRegTypeUninit);
485 /* convert the initialized reference "type" to a ClassObject pointer */
486 /* (does not expect uninit ref types or "zero") */
487 static ClassObject* regTypeInitializedReferenceToClass(RegType type)
489 assert(regTypeIsReference(type) && type != kRegTypeZero);
490 if ((type & 0x01) == 0) {
491 return (ClassObject*) type;
493 //LOG_VFY("VFY: attempted to use uninitialized reference\n");
498 /* extract the index into the uninitialized instance map table */
499 static inline int regTypeToUninitIndex(RegType type) {
500 assert(regTypeIsUninitReference(type));
501 return (type & ~kRegTypeUninitMask) >> kRegTypeUninitShift;
504 /* convert the reference "type" to a ClassObject pointer */
505 static ClassObject* regTypeReferenceToClass(RegType type,
506 const UninitInstanceMap* uninitMap)
508 assert(regTypeIsReference(type) && type != kRegTypeZero);
509 if (regTypeIsUninitReference(type)) {
510 assert(uninitMap != NULL);
511 return dvmGetUninitInstance(uninitMap, regTypeToUninitIndex(type));
513 return (ClassObject*) type;
517 /* convert the ClassObject pointer to an (initialized) register type */
518 static inline RegType regTypeFromClass(ClassObject* clazz) {
522 /* return the RegType for the uninitialized reference in slot "uidx" */
523 static RegType regTypeFromUninitIndex(int uidx) {
524 return (u4) (kRegTypeUninit | (uidx << kRegTypeUninitShift));
529 * ===========================================================================
530 * Signature operations
531 * ===========================================================================
535 * Is this method a constructor?
537 static bool isInitMethod(const Method* meth)
539 return (*meth->name == '<' && strcmp(meth->name+1, "init>") == 0);
543 * Is this method a class initializer?
546 static bool isClassInitMethod(const Method* meth)
548 return (*meth->name == '<' && strcmp(meth->name+1, "clinit>") == 0);
553 * Look up a class reference given as a simple string descriptor.
555 * If we can't find it, return a generic substitute when possible.
557 static ClassObject* lookupClassByDescriptor(const Method* meth,
558 const char* pDescriptor, VerifyError* pFailure)
561 * The javac compiler occasionally puts references to nonexistent
562 * classes in signatures. For example, if you have a non-static
563 * inner class with no constructor, the compiler provides
564 * a private <init> for you. Constructing the class
565 * requires <init>(parent), but the outer class can't call
566 * that because the method is private. So the compiler
567 * generates a package-scope <init>(parent,bogus) method that
568 * just calls the regular <init> (the "bogus" part being necessary
569 * to distinguish the signature of the synthetic method).
570 * Treating the bogus class as an instance of java.lang.Object
571 * allows the verifier to process the class successfully.
574 //LOGI("Looking up '%s'\n", typeStr);
576 clazz = dvmFindClassNoInit(pDescriptor, meth->clazz->classLoader);
578 dvmClearOptException(dvmThreadSelf());
579 if (strchr(pDescriptor, '$') != NULL) {
580 LOGV("VFY: unable to find class referenced in signature (%s)\n",
583 LOG_VFY("VFY: unable to find class referenced in signature (%s)\n",
587 if (pDescriptor[0] == '[') {
588 /* We are looking at an array descriptor. */
591 * There should never be a problem loading primitive arrays.
593 if (pDescriptor[1] != 'L' && pDescriptor[1] != '[') {
594 LOG_VFY("VFY: invalid char in signature in '%s'\n",
596 *pFailure = VERIFY_ERROR_GENERIC;
600 * Try to continue with base array type. This will let
601 * us pass basic stuff (e.g. get array len) that wouldn't
602 * fly with an Object. This is NOT correct if the
603 * missing type is a primitive array, but we should never
604 * have a problem loading those. (I'm not convinced this
605 * is correct or even useful. Just use Object here?)
607 clazz = dvmFindClassNoInit("[Ljava/lang/Object;",
608 meth->clazz->classLoader);
609 } else if (pDescriptor[0] == 'L') {
611 * We are looking at a non-array reference descriptor;
612 * try to continue with base reference type.
614 clazz = gDvm.classJavaLangObject;
616 /* We are looking at a primitive type. */
617 LOG_VFY("VFY: invalid char in signature in '%s'\n", pDescriptor);
618 *pFailure = VERIFY_ERROR_GENERIC;
622 *pFailure = VERIFY_ERROR_GENERIC;
626 if (dvmIsPrimitiveClass(clazz)) {
627 LOG_VFY("VFY: invalid use of primitive type '%s'\n", pDescriptor);
628 *pFailure = VERIFY_ERROR_GENERIC;
636 * Look up a class reference in a signature. Could be an arg or the
639 * Advances "*pSig" to the last character in the signature (that is, to
642 * NOTE: this is also expected to verify the signature.
644 static ClassObject* lookupSignatureClass(const Method* meth, const char** pSig,
645 VerifyError* pFailure)
647 const char* sig = *pSig;
648 const char* endp = sig;
650 assert(sig != NULL && *sig == 'L');
652 while (*++endp != ';' && *endp != '\0')
655 LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
656 *pFailure = VERIFY_ERROR_GENERIC;
660 endp++; /* Advance past the ';'. */
661 int typeLen = endp - sig;
662 char typeStr[typeLen+1]; /* +1 for the '\0' */
663 memcpy(typeStr, sig, typeLen);
664 typeStr[typeLen] = '\0';
666 *pSig = endp - 1; /* - 1 so that *pSig points at, not past, the ';' */
668 return lookupClassByDescriptor(meth, typeStr, pFailure);
672 * Look up an array class reference in a signature. Could be an arg or the
675 * Advances "*pSig" to the last character in the signature.
677 * NOTE: this is also expected to verify the signature.
679 static ClassObject* lookupSignatureArrayClass(const Method* meth,
680 const char** pSig, VerifyError* pFailure)
682 const char* sig = *pSig;
683 const char* endp = sig;
685 assert(sig != NULL && *sig == '[');
688 while (*++endp == '[' && *endp != '\0')
692 while (*++endp != ';' && *endp != '\0')
695 LOG_VFY("VFY: bad signature component '%s' (missing ';')\n", sig);
696 *pFailure = VERIFY_ERROR_GENERIC;
701 int typeLen = endp - sig +1;
702 char typeStr[typeLen+1];
703 memcpy(typeStr, sig, typeLen);
704 typeStr[typeLen] = '\0';
708 return lookupClassByDescriptor(meth, typeStr, pFailure);
712 * Set the register types for the first instruction in the method based on
713 * the method signature.
715 * This has the side-effect of validating the signature.
717 * Returns "true" on success.
719 static bool setTypesFromSignature(const Method* meth, RegType* regTypes,
720 UninitInstanceMap* uninitMap)
722 DexParameterIterator iterator;
723 int actualArgs, expectedArgs, argStart;
724 VerifyError failure = VERIFY_ERROR_NONE;
726 dexParameterIteratorInit(&iterator, &meth->prototype);
727 argStart = meth->registersSize - meth->insSize;
728 expectedArgs = meth->insSize; /* long/double count as two */
731 assert(argStart >= 0); /* should have been verified earlier */
734 * Include the "this" pointer.
736 if (!dvmIsStaticMethod(meth)) {
738 * If this is a constructor for a class other than java.lang.Object,
739 * mark the first ("this") argument as uninitialized. This restricts
740 * field access until the superclass constructor is called.
742 if (isInitMethod(meth) && meth->clazz != gDvm.classJavaLangObject) {
743 int uidx = dvmSetUninitInstance(uninitMap, kUninitThisArgAddr,
746 regTypes[argStart + actualArgs] = regTypeFromUninitIndex(uidx);
748 regTypes[argStart + actualArgs] = regTypeFromClass(meth->clazz);
754 const char* descriptor = dexParameterIteratorNextDescriptor(&iterator);
756 if (descriptor == NULL) {
760 if (actualArgs >= expectedArgs) {
761 LOG_VFY("VFY: expected %d args, found more (%s)\n",
762 expectedArgs, descriptor);
766 switch (*descriptor) {
770 * We assume that reference arguments are initialized. The
771 * only way it could be otherwise (assuming the caller was
772 * verified) is if the current method is <init>, but in that
773 * case it's effectively considered initialized the instant
774 * we reach here (in the sense that we can return without
775 * doing anything or call virtual methods).
779 lookupClassByDescriptor(meth, descriptor, &failure);
780 if (!VERIFY_OK(failure))
782 regTypes[argStart + actualArgs] = regTypeFromClass(clazz);
787 regTypes[argStart + actualArgs] = kRegTypeBoolean;
791 regTypes[argStart + actualArgs] = kRegTypeChar;
795 regTypes[argStart + actualArgs] = kRegTypeByte;
799 regTypes[argStart + actualArgs] = kRegTypeInteger;
803 regTypes[argStart + actualArgs] = kRegTypeShort;
807 regTypes[argStart + actualArgs] = kRegTypeFloat;
811 regTypes[argStart + actualArgs] = kRegTypeDoubleLo;
812 regTypes[argStart + actualArgs +1] = kRegTypeDoubleHi;
816 regTypes[argStart + actualArgs] = kRegTypeLongLo;
817 regTypes[argStart + actualArgs +1] = kRegTypeLongHi;
821 LOG_VFY("VFY: unexpected signature type char '%c'\n", *descriptor);
826 if (actualArgs != expectedArgs) {
827 LOG_VFY("VFY: expected %d args, found %d\n", expectedArgs, actualArgs);
831 const char* descriptor = dexProtoGetReturnType(&meth->prototype);
834 * Validate return type. We don't do the type lookup; just want to make
835 * sure that it has the right format. Only major difference from the
836 * method argument format is that 'V' is supported.
838 switch (*descriptor) {
848 if (*(descriptor+1) != '\0')
852 /* single/multi, object/primitive */
853 while (*++descriptor == '[')
855 if (*descriptor == 'L') {
856 while (*++descriptor != ';' && *descriptor != '\0')
858 if (*descriptor != ';')
861 if (*(descriptor+1) != '\0')
866 /* could be more thorough here, but shouldn't be required */
867 while (*++descriptor != ';' && *descriptor != '\0')
869 if (*descriptor != ';')
879 // LOG_VFY_METH(meth, "VFY: bad sig\n");
884 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
885 LOG_VFY("VFY: bad signature '%s' for %s.%s\n",
886 desc, meth->clazz->descriptor, meth->name);
893 * Return the register type for the method. We can't just use the
894 * already-computed DalvikJniReturnType, because if it's a reference type
895 * we need to do the class lookup.
897 * Returned references are assumed to be initialized.
899 * Returns kRegTypeUnknown for "void".
901 static RegType getMethodReturnType(const Method* meth)
904 const char* descriptor = dexProtoGetReturnType(&meth->prototype);
906 switch (*descriptor) {
908 type = kRegTypeInteger;
914 type = kRegTypeShort;
920 type = kRegTypeBoolean;
923 type = kRegTypeUnknown;
926 type = kRegTypeFloat;
929 type = kRegTypeDoubleLo;
932 type = kRegTypeLongLo;
937 VerifyError failure = VERIFY_ERROR_NONE;
939 lookupClassByDescriptor(meth, descriptor, &failure);
940 assert(VERIFY_OK(failure));
941 type = regTypeFromClass(clazz);
945 /* we verified signature return type earlier, so this is impossible */
947 type = kRegTypeConflict;
955 * Convert a single-character signature value (i.e. a primitive type) to
956 * the corresponding RegType. This is intended for access to object fields
957 * holding primitive types.
959 * Returns kRegTypeUnknown for objects, arrays, and void.
961 static RegType primSigCharToRegType(char sigChar)
967 type = kRegTypeInteger;
973 type = kRegTypeShort;
979 type = kRegTypeBoolean;
982 type = kRegTypeFloat;
985 type = kRegTypeDoubleLo;
988 type = kRegTypeLongLo;
993 type = kRegTypeUnknown;
997 type = kRegTypeUnknown;
1005 * Verify the arguments to a method. We're executing in "method", making
1006 * a call to the method reference in vB.
1008 * If this is a "direct" invoke, we allow calls to <init>. For calls to
1009 * <init>, the first argument may be an uninitialized reference. Otherwise,
1010 * calls to anything starting with '<' will be rejected, as will any
1011 * uninitialized reference arguments.
1013 * For non-static method calls, this will verify that the method call is
1014 * appropriate for the "this" argument.
1016 * The method reference is in vBBBB. The "isRange" parameter determines
1017 * whether we use 0-4 "args" values or a range of registers defined by
1020 * Widening conversions on integers and references are allowed, but
1021 * narrowing conversions are not.
1023 * Returns the resolved method on success, NULL on failure (with *pFailure
1024 * set appropriately).
1026 static Method* verifyInvocationArgs(const Method* meth, const RegType* insnRegs,
1027 const int insnRegCount, const DecodedInstruction* pDecInsn,
1028 UninitInstanceMap* uninitMap, MethodType methodType, bool isRange,
1029 bool isSuper, VerifyError* pFailure)
1032 char* sigOriginal = NULL;
1035 * Resolve the method. This could be an abstract or concrete method
1036 * depending on what sort of call we're making.
1038 if (methodType == METHOD_INTERFACE) {
1039 resMethod = dvmOptResolveInterfaceMethod(meth->clazz, pDecInsn->vB);
1041 resMethod = dvmOptResolveMethod(meth->clazz, pDecInsn->vB, methodType,
1044 if (resMethod == NULL) {
1045 /* failed; print a meaningful failure message */
1046 DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
1047 const DexMethodId* pMethodId;
1048 const char* methodName;
1050 const char* classDescriptor;
1052 pMethodId = dexGetMethodId(pDexFile, pDecInsn->vB);
1053 methodName = dexStringById(pDexFile, pMethodId->nameIdx);
1054 methodDesc = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
1055 classDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
1057 if (!gDvm.optimizing) {
1058 char* dotMissingClass = dvmDescriptorToDot(classDescriptor);
1059 char* dotMethClass = dvmDescriptorToDot(meth->clazz->descriptor);
1060 //char* curMethodDesc =
1061 // dexProtoCopyMethodDescriptor(&meth->prototype);
1063 LOGI("Could not find method %s.%s, referenced from "
1065 dotMissingClass, methodName/*, methodDesc*/,
1066 dotMethClass, meth->name/*, curMethodDesc*/);
1068 free(dotMissingClass);
1070 //free(curMethodDesc);
1073 LOG_VFY("VFY: unable to resolve %s method %u: %s.%s %s\n",
1074 dvmMethodTypeStr(methodType), pDecInsn->vB,
1075 classDescriptor, methodName, methodDesc);
1077 if (VERIFY_OK(*pFailure)) /* not set for interface resolve */
1078 *pFailure = VERIFY_ERROR_NO_METHOD;
1083 * Only time you can explicitly call a method starting with '<' is when
1084 * making a "direct" invocation on "<init>". There are additional
1085 * restrictions but we don't enforce them here.
1087 if (resMethod->name[0] == '<') {
1088 if (methodType != METHOD_DIRECT || !isInitMethod(resMethod)) {
1089 LOG_VFY("VFY: invalid call to %s.%s\n",
1090 resMethod->clazz->descriptor, resMethod->name);
1096 * If we're using invoke-super(method), make sure that the executing
1097 * method's class' superclass has a vtable entry for the target method.
1100 assert(methodType == METHOD_VIRTUAL);
1101 ClassObject* super = meth->clazz->super;
1102 if (super == NULL || resMethod->methodIndex > super->vtableCount) {
1103 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1104 LOG_VFY("VFY: invalid invoke-super from %s.%s to super %s.%s %s\n",
1105 meth->clazz->descriptor, meth->name,
1106 (super == NULL) ? "-" : super->descriptor,
1107 resMethod->name, desc);
1109 *pFailure = VERIFY_ERROR_NO_METHOD;
1115 * We use vAA as our expected arg count, rather than resMethod->insSize,
1116 * because we need to match the call to the signature. Also, we might
1117 * might be calling through an abstract method definition (which doesn't
1118 * have register count values).
1120 sigOriginal = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1121 const char* sig = sigOriginal;
1122 int expectedArgs = pDecInsn->vA;
1125 if (!isRange && expectedArgs > 5) {
1126 LOG_VFY("VFY: invalid arg count in non-range invoke (%d)\n",
1130 if (expectedArgs > meth->outsSize) {
1131 LOG_VFY("VFY: invalid arg count (%d) exceeds outsSize (%d)\n",
1132 expectedArgs, meth->outsSize);
1140 * Check the "this" argument, which must be an instance of the class
1141 * that declared the method. For an interface class, we don't do the
1142 * full interface merge, so we can't do a rigorous check here (which
1143 * is okay since we have to do it at runtime).
1145 if (!dvmIsStaticMethod(resMethod)) {
1146 ClassObject* actualThisRef;
1147 RegType actualArgType;
1149 actualArgType = getInvocationThis(insnRegs, insnRegCount, pDecInsn,
1151 if (!VERIFY_OK(*pFailure))
1154 if (regTypeIsUninitReference(actualArgType) && resMethod->name[0] != '<')
1156 LOG_VFY("VFY: 'this' arg must be initialized\n");
1159 if (methodType != METHOD_INTERFACE && actualArgType != kRegTypeZero) {
1160 actualThisRef = regTypeReferenceToClass(actualArgType, uninitMap);
1161 if (!dvmInstanceof(actualThisRef, resMethod->clazz)) {
1162 LOG_VFY("VFY: 'this' arg '%s' not instance of '%s'\n",
1163 actualThisRef->descriptor,
1164 resMethod->clazz->descriptor);
1172 * Process the target method's signature. This signature may or may not
1173 * have been verified, so we can't assume it's properly formed.
1175 while (*sig != '\0' && *sig != ')') {
1176 if (actualArgs >= expectedArgs) {
1177 LOG_VFY("VFY: expected %d args, found more (%c)\n",
1178 expectedArgs, *sig);
1184 getReg = pDecInsn->vC + actualArgs;
1186 getReg = pDecInsn->arg[actualArgs];
1191 ClassObject* clazz = lookupSignatureClass(meth, &sig, pFailure);
1192 if (!VERIFY_OK(*pFailure))
1194 verifyRegisterType(insnRegs, insnRegCount, getReg,
1195 regTypeFromClass(clazz), pFailure);
1196 if (!VERIFY_OK(*pFailure)) {
1197 LOG_VFY("VFY: bad arg %d (into %s)\n",
1198 actualArgs, clazz->descriptor);
1206 ClassObject* clazz =
1207 lookupSignatureArrayClass(meth, &sig, pFailure);
1208 if (!VERIFY_OK(*pFailure))
1210 verifyRegisterType(insnRegs, insnRegCount, getReg,
1211 regTypeFromClass(clazz), pFailure);
1212 if (!VERIFY_OK(*pFailure)) {
1213 LOG_VFY("VFY: bad arg %d (into %s)\n",
1214 actualArgs, clazz->descriptor);
1221 verifyRegisterType(insnRegs, insnRegCount, getReg,
1222 kRegTypeBoolean, pFailure);
1226 verifyRegisterType(insnRegs, insnRegCount, getReg,
1227 kRegTypeChar, pFailure);
1231 verifyRegisterType(insnRegs, insnRegCount, getReg,
1232 kRegTypeByte, pFailure);
1236 verifyRegisterType(insnRegs, insnRegCount, getReg,
1237 kRegTypeInteger, pFailure);
1241 verifyRegisterType(insnRegs, insnRegCount, getReg,
1242 kRegTypeShort, pFailure);
1246 verifyRegisterType(insnRegs, insnRegCount, getReg,
1247 kRegTypeFloat, pFailure);
1251 verifyRegisterType(insnRegs, insnRegCount, getReg,
1252 kRegTypeDoubleLo, pFailure);
1256 verifyRegisterType(insnRegs, insnRegCount, getReg,
1257 kRegTypeLongLo, pFailure);
1261 LOG_VFY("VFY: invocation target: bad signature type char '%c'\n",
1269 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1270 LOG_VFY("VFY: invocation target: bad signature '%s'\n", desc);
1275 if (actualArgs != expectedArgs) {
1276 LOG_VFY("VFY: expected %d args, found %d\n", expectedArgs, actualArgs);
1284 if (resMethod != NULL) {
1285 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype);
1286 LOG_VFY("VFY: rejecting call to %s.%s %s\n",
1287 resMethod->clazz->descriptor, resMethod->name, desc);
1293 if (*pFailure == VERIFY_ERROR_NONE)
1294 *pFailure = VERIFY_ERROR_GENERIC;
1299 * Get the class object for the type of data stored in a field. This isn't
1300 * stored in the Field struct, so we have to recover it from the signature.
1302 * This only works for reference types. Don't call this for primitive types.
1304 * If we can't find the class, we return java.lang.Object, so that
1305 * verification can continue if a field is only accessed in trivial ways.
1307 static ClassObject* getFieldClass(const Method* meth, const Field* field)
1309 ClassObject* fieldClass;
1310 const char* signature = field->signature;
1312 if ((*signature == 'L') || (*signature == '[')) {
1313 fieldClass = dvmFindClassNoInit(signature,
1314 meth->clazz->classLoader);
1319 if (fieldClass == NULL) {
1320 dvmClearOptException(dvmThreadSelf());
1321 LOGV("VFY: unable to find class '%s' for field %s.%s, trying Object\n",
1322 field->signature, meth->clazz->descriptor, field->name);
1323 fieldClass = gDvm.classJavaLangObject;
1325 assert(!dvmIsPrimitiveClass(fieldClass));
1332 * ===========================================================================
1333 * Register operations
1334 * ===========================================================================
1338 * Get the type of register N, verifying that the register is valid.
1340 * Sets "*pFailure" appropriately if the register number is out of range.
1342 static inline RegType getRegisterType(const RegType* insnRegs,
1343 const int insnRegCount, u4 vsrc, VerifyError* pFailure)
1345 if (vsrc >= (u4) insnRegCount) {
1346 *pFailure = VERIFY_ERROR_GENERIC;
1347 return kRegTypeUnknown;
1349 return insnRegs[vsrc];
1354 * Get the value from a register, and cast it to a ClassObject. Sets
1355 * "*pFailure" if something fails.
1357 * This fails if the register holds an uninitialized class.
1359 * If the register holds kRegTypeZero, this returns a NULL pointer.
1361 static ClassObject* getClassFromRegister(const RegType* insnRegs,
1362 const int insnRegCount, u4 vsrc, VerifyError* pFailure)
1364 ClassObject* clazz = NULL;
1367 /* get the element type of the array held in vsrc */
1368 type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
1369 if (!VERIFY_OK(*pFailure))
1372 /* if "always zero", we allow it to fail at runtime */
1373 if (type == kRegTypeZero)
1376 if (!regTypeIsReference(type)) {
1377 LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
1379 *pFailure = VERIFY_ERROR_GENERIC;
1382 if (regTypeIsUninitReference(type)) {
1383 LOG_VFY("VFY: register %u holds uninitialized reference\n", vsrc);
1384 *pFailure = VERIFY_ERROR_GENERIC;
1388 clazz = regTypeInitializedReferenceToClass(type);
1395 * Get the "this" pointer from a non-static method invocation. This
1396 * returns the RegType so the caller can decide whether it needs the
1397 * reference to be initialized or not. (Can also return kRegTypeZero
1398 * if the reference can only be zero at this point.)
1400 * The argument count is in vA, and the first argument is in vC, for both
1401 * "simple" and "range" versions. We just need to make sure vA is >= 1
1402 * and then return vC.
1404 static RegType getInvocationThis(const RegType* insnRegs,
1405 const int insnRegCount, const DecodedInstruction* pDecInsn,
1406 VerifyError* pFailure)
1408 RegType thisType = kRegTypeUnknown;
1410 if (pDecInsn->vA < 1) {
1411 LOG_VFY("VFY: invoke lacks 'this'\n");
1412 *pFailure = VERIFY_ERROR_GENERIC;
1416 /* get the element type of the array held in vsrc */
1417 thisType = getRegisterType(insnRegs, insnRegCount, pDecInsn->vC, pFailure);
1418 if (!VERIFY_OK(*pFailure)) {
1419 LOG_VFY("VFY: failed to get 'this' from register %u\n", pDecInsn->vC);
1423 if (!regTypeIsReference(thisType)) {
1424 LOG_VFY("VFY: tried to get class from non-ref register v%d (type=%d)\n",
1425 pDecInsn->vC, thisType);
1426 *pFailure = VERIFY_ERROR_GENERIC;
1435 * Set the type of register N, verifying that the register is valid. If
1436 * "newType" is the "Lo" part of a 64-bit value, register N+1 will be
1437 * set to "newType+1".
1439 * Sets "*pFailure" if the register number is out of range.
1441 static void setRegisterType(RegType* insnRegs, const int insnRegCount,
1442 u4 vdst, RegType newType, VerifyError* pFailure)
1444 //LOGD("set-reg v%u = %d\n", vdst, newType);
1446 case kRegTypeUnknown:
1447 case kRegTypeBoolean:
1450 case kRegTypePosByte:
1452 case kRegTypePosShort:
1454 case kRegTypeInteger:
1457 if (vdst >= (u4) insnRegCount) {
1458 *pFailure = VERIFY_ERROR_GENERIC;
1460 insnRegs[vdst] = newType;
1463 case kRegTypeLongLo:
1464 case kRegTypeDoubleLo:
1465 if (vdst+1 >= (u4) insnRegCount) {
1466 *pFailure = VERIFY_ERROR_GENERIC;
1468 insnRegs[vdst] = newType;
1469 insnRegs[vdst+1] = newType+1;
1472 case kRegTypeLongHi:
1473 case kRegTypeDoubleHi:
1474 /* should never set these explicitly */
1475 *pFailure = VERIFY_ERROR_GENERIC;
1478 case kRegTypeUninit:
1480 if (regTypeIsReference(newType)) {
1481 if (vdst >= (u4) insnRegCount) {
1482 *pFailure = VERIFY_ERROR_GENERIC;
1485 insnRegs[vdst] = newType;
1488 * In most circumstances we won't see a reference to a primitive
1489 * class here (e.g. "D"), since that would mean the object in the
1490 * register is actually a primitive type. It can happen as the
1491 * result of an assumed-successful check-cast instruction in
1492 * which the second argument refers to a primitive class. (In
1493 * practice, such an instruction will always throw an exception.)
1495 * This is not an issue for instructions like const-class, where
1496 * the object in the register is a java.lang.Class instance.
1500 /* bad - fall through */
1502 case kRegTypeConflict: // should only be set during a merge
1503 LOG_VFY("Unexpected set type %d\n", newType);
1505 *pFailure = VERIFY_ERROR_GENERIC;
1511 * Verify that the contents of the specified register have the specified
1512 * type (or can be converted to it through an implicit widening conversion).
1514 * In theory we could use this to modify the type of the source register,
1515 * e.g. a generic 32-bit constant, once used as a float, would thereafter
1516 * remain a float. There is no compelling reason to require this though.
1518 * If "vsrc" is a reference, both it and the "vsrc" register must be
1519 * initialized ("vsrc" may be Zero). This will verify that the value in
1520 * the register is an instance of checkType, or if checkType is an
1521 * interface, verify that the register implements checkType.
1523 static void verifyRegisterType(const RegType* insnRegs, const int insnRegCount,
1524 u4 vsrc, RegType checkType, VerifyError* pFailure)
1526 if (vsrc >= (u4) insnRegCount) {
1527 *pFailure = VERIFY_ERROR_GENERIC;
1531 RegType srcType = insnRegs[vsrc];
1533 //LOGD("check-reg v%u = %d\n", vsrc, checkType);
1534 switch (checkType) {
1536 case kRegTypeBoolean:
1537 case kRegTypePosByte:
1539 case kRegTypePosShort:
1542 case kRegTypeInteger:
1543 if (!canConvertTo1nr(srcType, checkType)) {
1544 LOG_VFY("VFY: register1 v%u type %d, wanted %d\n",
1545 vsrc, srcType, checkType);
1546 *pFailure = VERIFY_ERROR_GENERIC;
1549 case kRegTypeLongLo:
1550 case kRegTypeDoubleLo:
1551 if (vsrc+1 >= (u4) insnRegCount) {
1552 LOG_VFY("VFY: register2 v%u out of range (%d)\n",
1553 vsrc, insnRegCount);
1554 *pFailure = VERIFY_ERROR_GENERIC;
1555 } else if (insnRegs[vsrc+1] != srcType+1) {
1556 LOG_VFY("VFY: register2 v%u-%u values %d,%d\n",
1557 vsrc, vsrc+1, insnRegs[vsrc], insnRegs[vsrc+1]);
1558 *pFailure = VERIFY_ERROR_GENERIC;
1559 } else if (!canConvertTo2(srcType, checkType)) {
1560 LOG_VFY("VFY: register2 v%u type %d, wanted %d\n",
1561 vsrc, srcType, checkType);
1562 *pFailure = VERIFY_ERROR_GENERIC;
1566 case kRegTypeLongHi:
1567 case kRegTypeDoubleHi:
1570 case kRegTypeUnknown:
1571 case kRegTypeConflict:
1572 /* should never be checking for these explicitly */
1574 *pFailure = VERIFY_ERROR_GENERIC;
1576 case kRegTypeUninit:
1578 /* make sure checkType is initialized reference */
1579 if (!regTypeIsReference(checkType)) {
1580 LOG_VFY("VFY: unexpected check type %d\n", checkType);
1582 *pFailure = VERIFY_ERROR_GENERIC;
1585 if (regTypeIsUninitReference(checkType)) {
1586 LOG_VFY("VFY: uninitialized ref not expected as reg check\n");
1587 *pFailure = VERIFY_ERROR_GENERIC;
1590 /* make sure srcType is initialized reference or always-NULL */
1591 if (!regTypeIsReference(srcType)) {
1592 LOG_VFY("VFY: register1 v%u type %d, wanted ref\n", vsrc, srcType);
1593 *pFailure = VERIFY_ERROR_GENERIC;
1596 if (regTypeIsUninitReference(srcType)) {
1597 LOG_VFY("VFY: register1 v%u holds uninitialized ref\n", vsrc);
1598 *pFailure = VERIFY_ERROR_GENERIC;
1601 /* if the register isn't Zero, make sure it's an instance of check */
1602 if (srcType != kRegTypeZero) {
1603 ClassObject* srcClass = regTypeInitializedReferenceToClass(srcType);
1604 ClassObject* checkClass = regTypeInitializedReferenceToClass(checkType);
1605 assert(srcClass != NULL);
1606 assert(checkClass != NULL);
1608 if (dvmIsInterfaceClass(checkClass)) {
1610 * All objects implement all interfaces as far as the
1611 * verifier is concerned. The runtime has to sort it out.
1612 * See comments above findCommonSuperclass.
1615 if (srcClass != checkClass &&
1616 !dvmImplements(srcClass, checkClass))
1618 LOG_VFY("VFY: %s does not implement %s\n",
1619 srcClass->descriptor, checkClass->descriptor);
1620 *pFailure = VERIFY_ERROR_GENERIC;
1624 if (!dvmInstanceof(srcClass, checkClass)) {
1625 LOG_VFY("VFY: %s is not instance of %s\n",
1626 srcClass->descriptor, checkClass->descriptor);
1627 *pFailure = VERIFY_ERROR_GENERIC;
1636 * Set the type of the "result" register. Mostly this exists to expand
1637 * "insnRegCount" to encompass the result register.
1639 static void setResultRegisterType(RegType* insnRegs, const int insnRegCount,
1640 RegType newType, VerifyError* pFailure)
1642 setRegisterType(insnRegs, insnRegCount + kExtraRegs,
1643 RESULT_REGISTER(insnRegCount), newType, pFailure);
1648 * Update all registers holding "uninitType" to instead hold the
1649 * corresponding initialized reference type. This is called when an
1650 * appropriate <init> method is invoked -- all copies of the reference
1651 * must be marked as initialized.
1653 static void markRefsAsInitialized(RegType* insnRegs, int insnRegCount,
1654 UninitInstanceMap* uninitMap, RegType uninitType, VerifyError* pFailure)
1660 clazz = dvmGetUninitInstance(uninitMap, regTypeToUninitIndex(uninitType));
1661 if (clazz == NULL) {
1662 LOGE("VFY: unable to find type=0x%x (idx=%d)\n",
1663 uninitType, regTypeToUninitIndex(uninitType));
1664 *pFailure = VERIFY_ERROR_GENERIC;
1667 initType = regTypeFromClass(clazz);
1670 for (i = 0; i < insnRegCount; i++) {
1671 if (insnRegs[i] == uninitType) {
1672 insnRegs[i] = initType;
1676 //LOGD("VFY: marked %d registers as initialized\n", changed);
1677 assert(changed > 0);
1683 * We're creating a new instance of class C at address A. Any registers
1684 * holding instances previously created at address A must be initialized
1685 * by now. If not, we mark them as "conflict" to prevent them from being
1686 * used (otherwise, markRefsAsInitialized would mark the old ones and the
1687 * new ones at the same time).
1689 static void markUninitRefsAsInvalid(RegType* insnRegs, int insnRegCount,
1690 UninitInstanceMap* uninitMap, RegType uninitType)
1695 for (i = 0; i < insnRegCount; i++) {
1696 if (insnRegs[i] == uninitType) {
1697 insnRegs[i] = kRegTypeConflict;
1703 // LOGD("VFY: marked %d uninitialized registers as invalid\n", changed);
1707 * Find the start of the register set for the specified instruction in
1708 * the current method.
1710 static inline RegType* getRegisterLine(const RegisterTable* regTable,
1713 return regTable->addrRegs[insnIdx];
1717 * Copy a bunch of registers.
1719 static inline void copyRegisters(RegType* dst, const RegType* src,
1722 memcpy(dst, src, numRegs * sizeof(RegType));
1726 * Compare a bunch of registers.
1728 * Returns 0 if they match. Using this for a sort is unwise, since the
1729 * value can change based on machine endianness.
1731 static inline int compareRegisters(const RegType* src1, const RegType* src2,
1734 return memcmp(src1, src2, numRegs * sizeof(RegType));
1738 * Register type categories, for type checking.
1740 * The spec says category 1 includes boolean, byte, char, short, int, float,
1741 * reference, and returnAddress. Category 2 includes long and double.
1743 * We treat object references separately, so we have "category1nr". We
1744 * don't support jsr/ret, so there is no "returnAddress" type.
1746 typedef enum TypeCategory {
1747 kTypeCategoryUnknown = 0,
1748 kTypeCategory1nr, // byte, char, int, float, boolean
1749 kTypeCategory2, // long, double
1750 kTypeCategoryRef, // object reference
1754 * See if "type" matches "cat". All we're really looking for here is that
1755 * we're not mixing and matching 32-bit and 64-bit quantities, and we're
1756 * not mixing references with numerics. (For example, the arguments to
1757 * "a < b" could be integers of different sizes, but they must both be
1758 * integers. Dalvik is less specific about int vs. float, so we treat them
1759 * as equivalent here.)
1761 * For category 2 values, "type" must be the "low" half of the value.
1763 * Sets "*pFailure" if something looks wrong.
1765 static void checkTypeCategory(RegType type, TypeCategory cat,
1766 VerifyError* pFailure)
1769 case kTypeCategory1nr:
1774 case kRegTypeBoolean:
1775 case kRegTypePosByte:
1777 case kRegTypePosShort:
1780 case kRegTypeInteger:
1783 *pFailure = VERIFY_ERROR_GENERIC;
1788 case kTypeCategory2:
1790 case kRegTypeLongLo:
1791 case kRegTypeDoubleLo:
1794 *pFailure = VERIFY_ERROR_GENERIC;
1799 case kTypeCategoryRef:
1800 if (type != kRegTypeZero && !regTypeIsReference(type))
1801 *pFailure = VERIFY_ERROR_GENERIC;
1806 *pFailure = VERIFY_ERROR_GENERIC;
1812 * For a category 2 register pair, verify that "typeh" is the appropriate
1813 * high part for "typel".
1815 * Does not verify that "typel" is in fact the low part of a 64-bit
1818 static void checkWidePair(RegType typel, RegType typeh, VerifyError* pFailure)
1820 if ((typeh != typel+1))
1821 *pFailure = VERIFY_ERROR_GENERIC;
1825 * Implement category-1 "move" instructions. Copy a 32-bit value from
1828 * "insnRegCount" is the number of registers available. The "vdst" and
1829 * "vsrc" values are checked against this.
1831 static void copyRegister1(RegType* insnRegs, int insnRegCount, u4 vdst,
1832 u4 vsrc, TypeCategory cat, VerifyError* pFailure)
1834 RegType type = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
1835 if (VERIFY_OK(*pFailure))
1836 checkTypeCategory(type, cat, pFailure);
1837 if (VERIFY_OK(*pFailure))
1838 setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
1840 if (!VERIFY_OK(*pFailure)) {
1841 LOG_VFY("VFY: copy1 v%u<-v%u type=%d cat=%d\n", vdst, vsrc, type, cat);
1846 * Implement category-2 "move" instructions. Copy a 64-bit value from
1847 * "vsrc" to "vdst". This copies both halves of the register.
1849 static void copyRegister2(RegType* insnRegs, int insnRegCount, u4 vdst,
1850 u4 vsrc, VerifyError* pFailure)
1852 RegType typel = getRegisterType(insnRegs, insnRegCount, vsrc, pFailure);
1853 RegType typeh = getRegisterType(insnRegs, insnRegCount, vsrc+1, pFailure);
1854 if (VERIFY_OK(*pFailure)) {
1855 checkTypeCategory(typel, kTypeCategory2, pFailure);
1856 checkWidePair(typel, typeh, pFailure);
1858 if (VERIFY_OK(*pFailure))
1859 setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
1861 if (!VERIFY_OK(*pFailure)) {
1862 LOG_VFY("VFY: copy2 v%u<-v%u type=%d/%d\n", vdst, vsrc, typel, typeh);
1867 * Implement "move-result". Copy the category-1 value from the result
1868 * register to another register, and reset the result register.
1870 * We can't just call copyRegister1 with an altered insnRegCount,
1871 * because that would affect the test on "vdst" as well.
1873 static void copyResultRegister1(RegType* insnRegs, const int insnRegCount,
1874 u4 vdst, TypeCategory cat, VerifyError* pFailure)
1879 vsrc = RESULT_REGISTER(insnRegCount);
1880 type = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc, pFailure);
1881 if (VERIFY_OK(*pFailure))
1882 checkTypeCategory(type, cat, pFailure);
1883 if (VERIFY_OK(*pFailure)) {
1884 setRegisterType(insnRegs, insnRegCount, vdst, type, pFailure);
1885 insnRegs[vsrc] = kRegTypeUnknown;
1888 if (!VERIFY_OK(*pFailure)) {
1889 LOG_VFY("VFY: copyRes1 v%u<-v%u cat=%d type=%d\n",
1890 vdst, vsrc, cat, type);
1895 * Implement "move-result-wide". Copy the category-2 value from the result
1896 * register to another register, and reset the result register.
1898 * We can't just call copyRegister2 with an altered insnRegCount,
1899 * because that would affect the test on "vdst" as well.
1901 static void copyResultRegister2(RegType* insnRegs, const int insnRegCount,
1902 u4 vdst, VerifyError* pFailure)
1904 RegType typel, typeh;
1907 vsrc = RESULT_REGISTER(insnRegCount);
1908 typel = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc,
1910 typeh = getRegisterType(insnRegs, insnRegCount + kExtraRegs, vsrc+1,
1912 if (VERIFY_OK(*pFailure)) {
1913 checkTypeCategory(typel, kTypeCategory2, pFailure);
1914 checkWidePair(typel, typeh, pFailure);
1916 if (VERIFY_OK(*pFailure)) {
1917 setRegisterType(insnRegs, insnRegCount, vdst, typel, pFailure);
1918 insnRegs[vsrc] = kRegTypeUnknown;
1919 insnRegs[vsrc+1] = kRegTypeUnknown;
1922 if (!VERIFY_OK(*pFailure)) {
1923 LOG_VFY("VFY: copyRes2 v%u<-v%u type=%d/%d\n",
1924 vdst, vsrc, typel, typeh);
1929 * Verify types for a simple two-register instruction (e.g. "neg-int").
1930 * "dstType" is stored into vA, and "srcType" is verified against vB.
1932 static void checkUnop(RegType* insnRegs, const int insnRegCount,
1933 DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
1934 VerifyError* pFailure)
1936 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
1937 setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
1941 * We're performing an operation like "and-int/2addr" that can be
1942 * performed on booleans as well as integers. We get no indication of
1943 * boolean-ness, but we can infer it from the types of the arguments.
1945 * Assumes we've already validated reg1/reg2.
1947 * TODO: consider generalizing this. The key principle is that the
1948 * result of a bitwise operation can only be as wide as the widest of
1949 * the operands. You can safely AND/OR/XOR two chars together and know
1950 * you still have a char, so it's reasonable for the compiler or "dx"
1951 * to skip the int-to-char instruction. (We need to do this for boolean
1952 * because there is no int-to-boolean operation.)
1954 * Returns true if both args are Boolean, Zero, or One.
1956 static bool upcastBooleanOp(RegType* insnRegs, const int insnRegCount,
1959 RegType type1, type2;
1961 type1 = insnRegs[reg1];
1962 type2 = insnRegs[reg2];
1964 if ((type1 == kRegTypeBoolean || type1 == kRegTypeZero ||
1965 type1 == kRegTypeOne) &&
1966 (type2 == kRegTypeBoolean || type2 == kRegTypeZero ||
1967 type2 == kRegTypeOne))
1975 * Verify types for A two-register instruction with a literal constant
1976 * (e.g. "add-int/lit8"). "dstType" is stored into vA, and "srcType" is
1977 * verified against vB.
1979 * If "checkBooleanOp" is set, we use the constant value in vC.
1981 static void checkLitop(RegType* insnRegs, const int insnRegCount,
1982 DecodedInstruction* pDecInsn, RegType dstType, RegType srcType,
1983 bool checkBooleanOp, VerifyError* pFailure)
1985 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType, pFailure);
1986 if (VERIFY_OK(*pFailure) && checkBooleanOp) {
1987 assert(dstType == kRegTypeInteger);
1988 /* check vB with the call, then check the constant manually */
1989 if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vB)
1990 && (pDecInsn->vC == 0 || pDecInsn->vC == 1))
1992 dstType = kRegTypeBoolean;
1995 setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
1999 * Verify types for a simple three-register instruction (e.g. "add-int").
2000 * "dstType" is stored into vA, and "srcType1"/"srcType2" are verified
2003 static void checkBinop(RegType* insnRegs, const int insnRegCount,
2004 DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
2005 RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
2007 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType1,
2009 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vC, srcType2,
2011 if (VERIFY_OK(*pFailure) && checkBooleanOp) {
2012 assert(dstType == kRegTypeInteger);
2013 if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vB, pDecInsn->vC))
2014 dstType = kRegTypeBoolean;
2016 setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
2020 * Verify types for a binary "2addr" operation. "srcType1"/"srcType2"
2021 * are verified against vA/vB, then "dstType" is stored into vA.
2023 static void checkBinop2addr(RegType* insnRegs, const int insnRegCount,
2024 DecodedInstruction* pDecInsn, RegType dstType, RegType srcType1,
2025 RegType srcType2, bool checkBooleanOp, VerifyError* pFailure)
2027 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vA, srcType1,
2029 verifyRegisterType(insnRegs, insnRegCount, pDecInsn->vB, srcType2,
2031 if (VERIFY_OK(*pFailure) && checkBooleanOp) {
2032 assert(dstType == kRegTypeInteger);
2033 if (upcastBooleanOp(insnRegs, insnRegCount, pDecInsn->vA, pDecInsn->vB))
2034 dstType = kRegTypeBoolean;
2036 setRegisterType(insnRegs, insnRegCount, pDecInsn->vA, dstType, pFailure);
2040 * Treat right-shifting as a narrowing conversion when possible.
2042 * For example, right-shifting an int 24 times results in a value that can
2043 * be treated as a byte.
2045 * Things get interesting when contemplating sign extension. Right-
2046 * shifting an integer by 16 yields a value that can be represented in a
2047 * "short" but not a "char", but an unsigned right shift by 16 yields a
2048 * value that belongs in a char rather than a short. (Consider what would
2049 * happen if the result of the shift were cast to a char or short and then
2050 * cast back to an int. If sign extension, or the lack thereof, causes
2051 * a change in the 32-bit representation, then the conversion was lossy.)
2053 * A signed right shift by 17 on an integer results in a short. An unsigned
2054 * right shfit by 17 on an integer results in a posshort, which can be
2055 * assigned to a short or a char.
2057 * An unsigned right shift on a short can actually expand the result into
2058 * a 32-bit integer. For example, 0xfffff123 >>> 8 becomes 0x00fffff1,
2059 * which can't be represented in anything smaller than an int.
2061 * javac does not generate code that takes advantage of this, but some
2062 * of the code optimizers do. It's generally a peephole optimization
2063 * that replaces a particular sequence, e.g. (bipush 24, ishr, i2b) is
2064 * replaced by (bipush 24, ishr). Knowing that shifting a short 8 times
2065 * to the right yields a byte is really more than we need to handle the
2066 * code that's out there, but support is not much more complex than just
2069 * Right-shifting never yields a boolean value.
2071 * Returns the new register type.
2073 static RegType adjustForRightShift(RegType* workRegs, const int insnRegCount,
2074 int reg, unsigned int shiftCount, bool isUnsignedShift,
2075 VerifyError* pFailure)
2077 RegType srcType = getRegisterType(workRegs, insnRegCount, reg, pFailure);
2081 if (shiftCount == 0)
2085 if (isUnsignedShift)
2086 newType = kRegTypeInteger;
2090 if (shiftCount >= 32) {
2091 LOG_VFY("Got unexpectedly large shift count %u\n", shiftCount);
2097 case kRegTypeInteger: /* 32-bit signed value */
2098 case kRegTypeFloat: /* (allowed; treat same as int) */
2099 if (isUnsignedShift) {
2100 if (shiftCount > 24)
2101 newType = kRegTypePosByte;
2102 else if (shiftCount >= 16)
2103 newType = kRegTypeChar;
2105 if (shiftCount >= 24)
2106 newType = kRegTypeByte;
2107 else if (shiftCount >= 16)
2108 newType = kRegTypeShort;
2111 case kRegTypeShort: /* 16-bit signed value */
2112 if (isUnsignedShift) {
2113 /* default (kRegTypeInteger) is correct */
2115 if (shiftCount >= 8)
2116 newType = kRegTypeByte;
2119 case kRegTypePosShort: /* 15-bit unsigned value */
2120 if (shiftCount >= 8)
2121 newType = kRegTypePosByte;
2123 case kRegTypeChar: /* 16-bit unsigned value */
2125 newType = kRegTypePosByte;
2127 case kRegTypeByte: /* 8-bit signed value */
2128 /* defaults (u=kRegTypeInteger / s=srcType) are correct */
2130 case kRegTypePosByte: /* 7-bit unsigned value */
2131 /* always use newType=srcType */
2134 case kRegTypeZero: /* 1-bit unsigned value */
2136 case kRegTypeBoolean:
2138 newType = kRegTypeZero;
2141 /* long, double, references; shouldn't be here! */
2146 if (newType != srcType) {
2147 LOGVV("narrowing: %d(%d) --> %d to %d\n",
2148 shiftCount, isUnsignedShift, srcType, newType);
2150 LOGVV("not narrowed: %d(%d) --> %d\n",
2151 shiftCount, isUnsignedShift, srcType);
2158 * ===========================================================================
2160 * ===========================================================================
2164 * Compute the "class depth" of a class. This is the distance from the
2165 * class to the top of the tree, chasing superclass links. java.lang.Object
2166 * has a class depth of 0.
2168 static int getClassDepth(ClassObject* clazz)
2172 while (clazz->super != NULL) {
2173 clazz = clazz->super;
2180 * Given two classes, walk up the superclass tree to find a common
2181 * ancestor. (Called from findCommonSuperclass().)
2183 * TODO: consider caching the class depth in the class object so we don't
2184 * have to search for it here.
2186 static ClassObject* digForSuperclass(ClassObject* c1, ClassObject* c2)
2190 depth1 = getClassDepth(c1);
2191 depth2 = getClassDepth(c2);
2193 if (gDebugVerbose) {
2194 LOGVV("COMMON: %s(%d) + %s(%d)\n",
2195 c1->descriptor, depth1, c2->descriptor, depth2);
2198 /* pull the deepest one up */
2199 if (depth1 > depth2) {
2200 while (depth1 > depth2) {
2205 while (depth2 > depth1) {
2211 /* walk up in lock-step */
2216 assert(c1 != NULL && c2 != NULL);
2219 if (gDebugVerbose) {
2220 LOGVV(" : --> %s\n", c1->descriptor);
2226 * Merge two array classes. We can't use the general "walk up to the
2227 * superclass" merge because the superclass of an array is always Object.
2228 * We want String[] + Integer[] = Object[]. This works for higher dimensions
2229 * as well, e.g. String[][] + Integer[][] = Object[][].
2231 * If Foo1 and Foo2 are subclasses of Foo, Foo1[] + Foo2[] = Foo[].
2233 * If Class implements Type, Class[] + Type[] = Type[].
2235 * If the dimensions don't match, we want to convert to an array of Object
2236 * with the least dimension, e.g. String[][] + String[][][][] = Object[][].
2238 * This gets a little awkward because we may have to ask the VM to create
2239 * a new array type with the appropriate element and dimensions. However, we
2240 * shouldn't be doing this often.
2242 static ClassObject* findCommonArraySuperclass(ClassObject* c1, ClassObject* c2)
2244 ClassObject* arrayClass = NULL;
2245 ClassObject* commonElem;
2248 assert(c1->arrayDim > 0);
2249 assert(c2->arrayDim > 0);
2251 if (c1->arrayDim == c2->arrayDim) {
2252 //commonElem = digForSuperclass(c1->elementClass, c2->elementClass);
2253 commonElem = findCommonSuperclass(c1->elementClass, c2->elementClass);
2254 numDims = c1->arrayDim;
2256 if (c1->arrayDim < c2->arrayDim)
2257 numDims = c1->arrayDim;
2259 numDims = c2->arrayDim;
2260 commonElem = c1->super; // == java.lang.Object
2263 /* walk from the element to the (multi-)dimensioned array type */
2264 for (i = 0; i < numDims; i++) {
2265 arrayClass = dvmFindArrayClassForElement(commonElem);
2266 commonElem = arrayClass;
2269 LOGVV("ArrayMerge '%s' + '%s' --> '%s'\n",
2270 c1->descriptor, c2->descriptor, arrayClass->descriptor);
2275 * Find the first common superclass of the two classes. We're not
2276 * interested in common interfaces.
2278 * The easiest way to do this for concrete classes is to compute the "class
2279 * depth" of each, move up toward the root of the deepest one until they're
2280 * at the same depth, then walk both up to the root until they match.
2282 * If both classes are arrays of non-primitive types, we need to merge
2283 * based on array depth and element type.
2285 * If one class is an interface, we check to see if the other class/interface
2286 * (or one of its predecessors) implements the interface. If so, we return
2287 * the interface; otherwise, we return Object.
2289 * NOTE: we continue the tradition of "lazy interface handling". To wit,
2290 * suppose we have three classes:
2291 * One implements Fancy, Free
2292 * Two implements Fancy, Free
2293 * Three implements Free
2294 * where Fancy and Free are unrelated interfaces. The code requires us
2295 * to merge One into Two. Ideally we'd use a common interface, which
2296 * gives us a choice between Fancy and Free, and no guidance on which to
2297 * use. If we use Free, we'll be okay when Three gets merged in, but if
2298 * we choose Fancy, we're hosed. The "ideal" solution is to create a
2299 * set of common interfaces and carry that around, merging further references
2300 * into it. This is a pain. The easy solution is to simply boil them
2301 * down to Objects and let the runtime invokeinterface call fail, which
2304 static ClassObject* findCommonSuperclass(ClassObject* c1, ClassObject* c2)
2306 assert(!dvmIsPrimitiveClass(c1) && !dvmIsPrimitiveClass(c2));
2311 if (dvmIsInterfaceClass(c1) && dvmImplements(c2, c1)) {
2313 LOGVV("COMMON/I1: %s + %s --> %s\n",
2314 c1->descriptor, c2->descriptor, c1->descriptor);
2317 if (dvmIsInterfaceClass(c2) && dvmImplements(c1, c2)) {
2319 LOGVV("COMMON/I2: %s + %s --> %s\n",
2320 c1->descriptor, c2->descriptor, c2->descriptor);
2324 if (dvmIsArrayClass(c1) && dvmIsArrayClass(c2) &&
2325 !dvmIsPrimitiveClass(c1->elementClass) &&
2326 !dvmIsPrimitiveClass(c2->elementClass))
2328 return findCommonArraySuperclass(c1, c2);
2331 return digForSuperclass(c1, c2);
2335 * Merge two RegType values.
2337 * Sets "*pChanged" to "true" if the result doesn't match "type1".
2339 static RegType mergeTypes(RegType type1, RegType type2, bool* pChanged)
2344 * Check for trivial case so we don't have to hit memory.
2350 * Use the table if we can, and reject any attempts to merge something
2351 * from the table with a reference type.
2353 * The uninitialized table entry at index zero *will* show up as a
2354 * simple kRegTypeUninit value. Since this cannot be merged with
2355 * anything but itself, the rules do the right thing.
2357 if (type1 < kRegTypeMAX) {
2358 if (type2 < kRegTypeMAX) {
2359 result = gDvmMergeTab[type1][type2];
2361 /* simple + reference == conflict, usually */
2362 if (type1 == kRegTypeZero)
2365 result = kRegTypeConflict;
2368 if (type2 < kRegTypeMAX) {
2369 /* reference + simple == conflict, usually */
2370 if (type2 == kRegTypeZero)
2373 result = kRegTypeConflict;
2375 /* merging two references */
2376 if (regTypeIsUninitReference(type1) ||
2377 regTypeIsUninitReference(type2))
2379 /* can't merge uninit with anything but self */
2380 result = kRegTypeConflict;
2382 ClassObject* clazz1 = regTypeInitializedReferenceToClass(type1);
2383 ClassObject* clazz2 = regTypeInitializedReferenceToClass(type2);
2384 ClassObject* mergedClass;
2386 mergedClass = findCommonSuperclass(clazz1, clazz2);
2387 assert(mergedClass != NULL);
2388 result = regTypeFromClass(mergedClass);
2393 if (result != type1)
2399 * Control can transfer to "nextInsn".
2401 * Merge the registers from "workRegs" into "regTypes" at "nextInsn", and
2402 * set the "changed" flag on the target address if the registers have changed.
2404 static void updateRegisters(const Method* meth, InsnFlags* insnFlags,
2405 RegisterTable* regTable, int nextInsn, const RegType* workRegs)
2407 RegType* targetRegs = getRegisterLine(regTable, nextInsn);
2408 const int insnRegCount = meth->registersSize;
2411 if (!dvmInsnIsBranchTarget(insnFlags, nextInsn)) {
2412 LOGE("insnFlags[0x%x]=0x%08x\n", nextInsn, insnFlags[nextInsn]);
2413 LOGE(" In %s.%s %s\n",
2414 meth->clazz->descriptor, meth->name, meth->descriptor);
2419 if (!dvmInsnIsVisitedOrChanged(insnFlags, nextInsn)) {
2421 * We haven't processed this instruction before, and we haven't
2422 * touched the registers here, so there's nothing to "merge". Copy
2423 * the registers over and mark it as changed. (This is the only
2424 * way a register can transition out of "unknown", so this is not
2425 * just an optimization.)
2427 LOGVV("COPY into 0x%04x\n", nextInsn);
2428 copyRegisters(targetRegs, workRegs, insnRegCount + kExtraRegs);
2429 dvmInsnSetChanged(insnFlags, nextInsn, true);
2431 if (gDebugVerbose) {
2432 LOGVV("MERGE into 0x%04x\n", nextInsn);
2433 //dumpRegTypes(meth, insnFlags, targetRegs, 0, "targ", NULL, 0);
2434 //dumpRegTypes(meth, insnFlags, workRegs, 0, "work", NULL, 0);
2436 /* merge registers, set Changed only if different */
2437 bool changed = false;
2440 for (i = 0; i < insnRegCount + kExtraRegs; i++) {
2441 targetRegs[i] = mergeTypes(targetRegs[i], workRegs[i], &changed);
2444 if (gDebugVerbose) {
2445 //LOGI(" RESULT (changed=%d)\n", changed);
2446 //dumpRegTypes(meth, insnFlags, targetRegs, 0, "rslt", NULL, 0);
2450 dvmInsnSetChanged(insnFlags, nextInsn, true);
2456 * ===========================================================================
2458 * ===========================================================================
2462 * Look up an instance field, specified by "fieldIdx", that is going to be
2463 * accessed in object "objType". This resolves the field and then verifies
2464 * that the class containing the field is an instance of the reference in
2467 * It is possible for "objType" to be kRegTypeZero, meaning that we might
2468 * have a null reference. This is a runtime problem, so we allow it,
2469 * skipping some of the type checks.
2471 * In general, "objType" must be an initialized reference. However, we
2472 * allow it to be uninitialized if this is an "<init>" method and the field
2473 * is declared within the "objType" class.
2475 * Returns an InstField on success, returns NULL and sets "*pFailure"
2478 static InstField* getInstField(const Method* meth,
2479 const UninitInstanceMap* uninitMap, RegType objType, int fieldIdx,
2480 VerifyError* pFailure)
2482 InstField* instField = NULL;
2483 ClassObject* objClass;
2484 bool mustBeLocal = false;
2486 if (!regTypeIsReference(objType)) {
2487 LOG_VFY("VFY: attempt to access field in non-reference type %d\n",
2489 *pFailure = VERIFY_ERROR_GENERIC;
2493 instField = dvmOptResolveInstField(meth->clazz, fieldIdx, pFailure);
2494 if (instField == NULL) {
2495 LOG_VFY("VFY: unable to resolve instance field %u\n", fieldIdx);
2496 assert(!VERIFY_OK(*pFailure));
2500 if (objType == kRegTypeZero)
2504 * Access to fields in uninitialized objects is allowed if this is
2505 * the <init> method for the object and the field in question is
2506 * declared by this class.
2508 objClass = regTypeReferenceToClass(objType, uninitMap);
2509 assert(objClass != NULL);
2510 if (regTypeIsUninitReference(objType)) {
2511 if (!isInitMethod(meth) || meth->clazz != objClass) {
2512 LOG_VFY("VFY: attempt to access field via uninitialized ref\n");
2513 *pFailure = VERIFY_ERROR_GENERIC;
2519 if (!dvmInstanceof(objClass, instField->field.clazz)) {
2520 LOG_VFY("VFY: invalid field access (field %s.%s, through %s ref)\n",
2521 instField->field.clazz->descriptor, instField->field.name,
2522 objClass->descriptor);
2523 *pFailure = VERIFY_ERROR_NO_FIELD;
2528 /* for uninit ref, make sure it's defined by this class, not super */
2529 if (instField < objClass->ifields ||
2530 instField >= objClass->ifields + objClass->ifieldCount)
2532 LOG_VFY("VFY: invalid constructor field access (field %s in %s)\n",
2533 instField->field.name, objClass->descriptor);
2534 *pFailure = VERIFY_ERROR_GENERIC;
2544 * Look up a static field.
2546 * Returns a StaticField on success, returns NULL and sets "*pFailure"
2549 static StaticField* getStaticField(const Method* meth, int fieldIdx,
2550 VerifyError* pFailure)
2552 StaticField* staticField;
2554 staticField = dvmOptResolveStaticField(meth->clazz, fieldIdx, pFailure);
2555 if (staticField == NULL) {
2556 DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
2557 const DexFieldId* pFieldId;
2559 pFieldId = dexGetFieldId(pDexFile, fieldIdx);
2561 LOG_VFY("VFY: unable to resolve static field %u (%s) in %s\n", fieldIdx,
2562 dexStringById(pDexFile, pFieldId->nameIdx),
2563 dexStringByTypeIdx(pDexFile, pFieldId->classIdx));
2564 assert(!VERIFY_OK(*pFailure));
2573 * If "field" is marked "final", make sure this is the either <clinit>
2574 * or <init> as appropriate.
2576 * Sets "*pFailure" on failure.
2578 static void checkFinalFieldAccess(const Method* meth, const Field* field,
2579 VerifyError* pFailure)
2581 if (!dvmIsFinalField(field))
2584 /* make sure we're in the same class */
2585 if (meth->clazz != field->clazz) {
2586 LOG_VFY_METH(meth, "VFY: can't modify final field %s.%s\n",
2587 field->clazz->descriptor, field->name);
2588 *pFailure = VERIFY_ERROR_ACCESS_FIELD;
2593 * The VM spec descriptions of putfield and putstatic say that
2594 * IllegalAccessError is only thrown when the instructions appear
2595 * outside the declaring class. Our earlier attempts to restrict
2596 * final field modification to constructors are, therefore, wrong.
2599 /* make sure we're in the right kind of constructor */
2600 if (dvmIsStaticField(field)) {
2601 if (!isClassInitMethod(meth)) {
2603 "VFY: can't modify final static field outside <clinit>\n");
2604 *pFailure = VERIFY_ERROR_GENERIC;
2607 if (!isInitMethod(meth)) {
2609 "VFY: can't modify final field outside <init>\n");
2610 *pFailure = VERIFY_ERROR_GENERIC;
2617 * Make sure that the register type is suitable for use as an array index.
2619 * Sets "*pFailure" if not.
2621 static void checkArrayIndexType(const Method* meth, RegType regType,
2622 VerifyError* pFailure)
2624 if (VERIFY_OK(*pFailure)) {
2626 * The 1nr types are interchangeable at this level. We could
2627 * do something special if we can definitively identify it as a
2628 * float, but there's no real value in doing so.
2630 checkTypeCategory(regType, kTypeCategory1nr, pFailure);
2631 if (!VERIFY_OK(*pFailure)) {
2632 LOG_VFY_METH(meth, "Invalid reg type for array index (%d)\n",
2639 * Check constraints on constructor return. Specifically, make sure that
2640 * the "this" argument got initialized.
2642 * The "this" argument to <init> uses code offset kUninitThisArgAddr, which
2643 * puts it at the start of the list in slot 0. If we see a register with
2644 * an uninitialized slot 0 reference, we know it somehow didn't get
2647 * Returns "true" if all is well.
2649 static bool checkConstructorReturn(const Method* meth, const RegType* insnRegs,
2650 const int insnRegCount)
2654 if (!isInitMethod(meth))
2657 RegType uninitThis = regTypeFromUninitIndex(kUninitThisArgSlot);
2659 for (i = 0; i < insnRegCount; i++) {
2660 if (insnRegs[i] == uninitThis) {
2661 LOG_VFY("VFY: <init> returning without calling superclass init\n");
2669 * Verify that the target instruction is not "move-exception". It's important
2670 * that the only way to execute a move-exception is as the first instruction
2671 * of an exception handler.
2673 * Returns "true" if all is well, "false" if the target instruction is
2676 static bool checkMoveException(const Method* meth, int insnIdx,
2677 const char* logNote)
2679 assert(insnIdx >= 0 && insnIdx < (int)dvmGetMethodInsnsSize(meth));
2681 if ((meth->insns[insnIdx] & 0xff) == OP_MOVE_EXCEPTION) {
2682 LOG_VFY("VFY: invalid use of move-exception\n");
2689 * For the "move-exception" instruction at "insnIdx", which must be at an
2690 * exception handler address, determine the first common superclass of
2691 * all exceptions that can land here. (For javac output, we're probably
2692 * looking at multiple spans of bytecode covered by one "try" that lands
2693 * at an exception-specific "catch", but in general the handler could be
2694 * shared for multiple exceptions.)
2696 * Returns NULL if no matching exception handler can be found, or if the
2697 * exception is not a subclass of Throwable.
2699 static ClassObject* getCaughtExceptionType(const Method* meth, int insnIdx,
2700 VerifyError* pFailure)
2702 VerifyError localFailure;
2703 const DexCode* pCode;
2705 ClassObject* commonSuper = NULL;
2706 bool foundPossibleHandler = false;
2711 pDexFile = meth->clazz->pDvmDex->pDexFile;
2712 pCode = dvmGetMethodCode(meth);
2714 if (pCode->triesSize != 0) {
2715 handlersSize = dexGetHandlersSize(pCode);
2716 offset = dexGetFirstHandlerOffset(pCode);
2722 for (i = 0; i < handlersSize; i++) {
2723 DexCatchIterator iterator;
2724 dexCatchIteratorInit(&iterator, pCode, offset);
2727 const DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
2729 if (handler == NULL) {
2733 if (handler->address == (u4) insnIdx) {
2735 foundPossibleHandler = true;
2737 if (handler->typeIdx == kDexNoIndex)
2738 clazz = gDvm.classJavaLangThrowable;
2740 clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx,
2743 if (clazz == NULL) {
2744 LOG_VFY("VFY: unable to resolve exception class %u (%s)\n",
2746 dexStringByTypeIdx(pDexFile, handler->typeIdx));
2747 /* TODO: do we want to keep going? If we don't fail
2748 * this we run the risk of having a non-Throwable
2749 * introduced at runtime. However, that won't pass
2750 * an instanceof test, so is essentially harmless. */
2752 if (commonSuper == NULL)
2753 commonSuper = clazz;
2755 commonSuper = findCommonSuperclass(clazz, commonSuper);
2760 offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
2763 if (commonSuper == NULL) {
2764 /* no catch blocks, or no catches with classes we can find */
2766 "VFY: unable to find exception handler at addr 0x%x\n", insnIdx);
2767 *pFailure = VERIFY_ERROR_GENERIC;
2769 // TODO: verify the class is an instance of Throwable?
2776 * Initialize the RegisterTable.
2778 * Every instruction address can have a different set of information about
2779 * what's in which register, but for verification purposes we only need to
2780 * store it at branch target addresses (because we merge into that).
2782 * By zeroing out the storage we are effectively initializing the register
2783 * information to kRegTypeUnknown.
2785 static bool initRegisterTable(const Method* meth, const InsnFlags* insnFlags,
2786 RegisterTable* regTable, RegisterTrackingMode trackRegsFor)
2788 const int insnsSize = dvmGetMethodInsnsSize(meth);
2791 regTable->insnRegCountPlus = meth->registersSize + kExtraRegs;
2792 regTable->addrRegs = (RegType**) calloc(insnsSize, sizeof(RegType*));
2793 if (regTable->addrRegs == NULL)
2796 assert(insnsSize > 0);
2799 * "All" means "every address that holds the start of an instruction".
2800 * "Branches" and "GcPoints" mean just those addresses.
2802 * "GcPoints" fills about half the addresses, "Branches" about 15%.
2804 int interestingCount = 0;
2805 //int insnCount = 0;
2807 for (i = 0; i < insnsSize; i++) {
2810 switch (trackRegsFor) {
2812 interesting = dvmInsnIsOpcode(insnFlags, i);
2814 case kTrackRegsGcPoints:
2815 interesting = dvmInsnIsGcPoint(insnFlags, i) ||
2816 dvmInsnIsBranchTarget(insnFlags, i);
2818 case kTrackRegsBranches:
2819 interesting = dvmInsnIsBranchTarget(insnFlags, i);
2829 /* count instructions, for display only */
2830 //if (dvmInsnIsOpcode(insnFlags, i))
2834 regTable->regAlloc = (RegType*)
2835 calloc(regTable->insnRegCountPlus * interestingCount, sizeof(RegType));
2836 if (regTable->regAlloc == NULL)
2839 RegType* regPtr = regTable->regAlloc;
2840 for (i = 0; i < insnsSize; i++) {
2843 switch (trackRegsFor) {
2845 interesting = dvmInsnIsOpcode(insnFlags, i);
2847 case kTrackRegsGcPoints:
2848 interesting = dvmInsnIsGcPoint(insnFlags, i) ||
2849 dvmInsnIsBranchTarget(insnFlags, i);
2851 case kTrackRegsBranches:
2852 interesting = dvmInsnIsBranchTarget(insnFlags, i);
2860 regTable->addrRegs[i] = regPtr;
2861 regPtr += regTable->insnRegCountPlus;
2865 //LOGD("Tracking registers for %d, total %d of %d(%d) (%d%%)\n",
2866 // TRACK_REGS_FOR, interestingCount, insnCount, insnsSize,
2867 // (interestingCount*100) / insnCount);
2869 assert(regPtr - regTable->regAlloc ==
2870 regTable->insnRegCountPlus * interestingCount);
2871 assert(regTable->addrRegs[0] != NULL);
2877 * Verify that the arguments in a filled-new-array instruction are valid.
2879 * "resClass" is the class refered to by pDecInsn->vB.
2881 static void verifyFilledNewArrayRegs(const Method* meth,
2882 const RegType* insnRegs, const int insnRegCount,
2883 const DecodedInstruction* pDecInsn, ClassObject* resClass, bool isRange,
2884 VerifyError* pFailure)
2886 u4 argCount = pDecInsn->vA;
2887 RegType expectedType;
2888 PrimitiveType elemType;
2891 assert(dvmIsArrayClass(resClass));
2892 elemType = resClass->elementClass->primitiveType;
2893 if (elemType == PRIM_NOT) {
2894 expectedType = regTypeFromClass(resClass->elementClass);
2896 expectedType = primitiveTypeToRegType(elemType);
2898 //LOGI("filled-new-array: %s -> %d\n", resClass->descriptor, expectedType);
2901 * Verify each register. If "argCount" is bad, verifyRegisterType()
2902 * will run off the end of the list and fail. It's legal, if silly,
2903 * for argCount to be zero.
2905 for (ui = 0; ui < argCount; ui++) {
2909 getReg = pDecInsn->vC + ui;
2911 getReg = pDecInsn->arg[ui];
2913 verifyRegisterType(insnRegs, insnRegCount, getReg, expectedType,
2915 if (!VERIFY_OK(*pFailure)) {
2916 LOG_VFY("VFY: filled-new-array arg %u(%u) not valid\n", ui, getReg);
2924 * Replace an instruction with "throw-verification-error". This allows us to
2925 * defer error reporting until the code path is first used.
2927 * This is expected to be called during "just in time" verification, not
2928 * from within dexopt. (Verification failures in dexopt will result in
2929 * postponement of verification to first use of the class.)
2931 * The throw-verification-error instruction requires two code units. Some
2932 * of the replaced instructions require three; the third code unit will
2933 * receive a "nop". The instruction's length will be left unchanged
2936 * The verifier explicitly locks out breakpoint activity, so there should
2937 * be no clashes with the debugger.
2939 * Returns "true" on success.
2941 static bool replaceFailingInstruction(const Method* meth, InsnFlags* insnFlags,
2942 int insnIdx, VerifyError failure)
2944 VerifyErrorRefType refType;
2945 const u2* oldInsns = meth->insns + insnIdx;
2946 u2 oldInsn = *oldInsns;
2947 bool result = false;
2949 if (gDvm.optimizing)
2950 LOGD("Weird: RFI during dexopt?");
2952 //LOGD(" was 0x%04x\n", oldInsn);
2953 u2* newInsns = (u2*) meth->insns + insnIdx;
2956 * Generate the new instruction out of the old.
2958 * First, make sure this is an instruction we're expecting to stomp on.
2960 switch (oldInsn & 0xff) {
2961 case OP_CONST_CLASS: // insn[1] == class ref, 2 bytes
2963 case OP_INSTANCE_OF:
2964 case OP_NEW_INSTANCE:
2966 case OP_FILLED_NEW_ARRAY: // insn[1] == class ref, 3 bytes
2967 case OP_FILLED_NEW_ARRAY_RANGE:
2968 refType = VERIFY_ERROR_REF_CLASS;
2971 case OP_IGET: // insn[1] == field ref, 2 bytes
2972 case OP_IGET_BOOLEAN:
2977 case OP_IGET_OBJECT:
2979 case OP_IPUT_BOOLEAN:
2984 case OP_IPUT_OBJECT:
2986 case OP_SGET_BOOLEAN:
2991 case OP_SGET_OBJECT:
2993 case OP_SPUT_BOOLEAN:
2998 case OP_SPUT_OBJECT:
2999 refType = VERIFY_ERROR_REF_FIELD;
3002 case OP_INVOKE_VIRTUAL: // insn[1] == method ref, 3 bytes
3003 case OP_INVOKE_VIRTUAL_RANGE:
3004 case OP_INVOKE_SUPER:
3005 case OP_INVOKE_SUPER_RANGE:
3006 case OP_INVOKE_DIRECT:
3007 case OP_INVOKE_DIRECT_RANGE:
3008 case OP_INVOKE_STATIC:
3009 case OP_INVOKE_STATIC_RANGE:
3010 case OP_INVOKE_INTERFACE:
3011 case OP_INVOKE_INTERFACE_RANGE:
3012 refType = VERIFY_ERROR_REF_METHOD;
3016 /* could handle this in a generic way, but this is probably safer */
3017 LOG_VFY("GLITCH: verifier asked to replace opcode 0x%02x\n",
3022 /* write a NOP over the third code unit, if necessary */
3023 int width = dvmInsnGetWidth(insnFlags, insnIdx);
3029 dvmDexChangeDex2(meth->clazz->pDvmDex, newInsns+2, OP_NOP);
3030 //newInsns[2] = OP_NOP;
3034 LOGE("ERROR: stomped a %d-unit instruction with a verifier error\n",
3039 /* encode the opcode, with the failure code in the high byte */
3040 u2 newVal = OP_THROW_VERIFICATION_ERROR |
3041 (failure << 8) | (refType << (8 + kVerifyErrorRefTypeShift));
3042 //newInsns[0] = newVal;
3043 dvmDexChangeDex2(meth->clazz->pDvmDex, newInsns, newVal);
3053 * ===========================================================================
3054 * Entry point and driver loop
3055 * ===========================================================================
3059 * Entry point for the detailed code-flow analysis.
3061 bool dvmVerifyCodeFlow(VerifierData* vdata)
3063 bool result = false;
3064 const Method* meth = vdata->method;
3065 const int insnsSize = vdata->insnsSize;
3066 const bool generateRegisterMap = gDvm.generateRegisterMaps;
3067 RegisterTable regTable;
3069 memset(®Table, 0, sizeof(regTable));
3072 checkMergeTab(); // only need to do this if table gets updated
3076 * We rely on these for verification of const-class, const-string,
3077 * and throw instructions. Make sure we have them.
3079 if (gDvm.classJavaLangClass == NULL)
3080 gDvm.classJavaLangClass =
3081 dvmFindSystemClassNoInit("Ljava/lang/Class;");
3082 if (gDvm.classJavaLangString == NULL)
3083 gDvm.classJavaLangString =
3084 dvmFindSystemClassNoInit("Ljava/lang/String;");
3085 if (gDvm.classJavaLangThrowable == NULL) {
3086 gDvm.classJavaLangThrowable =
3087 dvmFindSystemClassNoInit("Ljava/lang/Throwable;");
3088 gDvm.offJavaLangThrowable_cause =
3089 dvmFindFieldOffset(gDvm.classJavaLangThrowable,
3090 "cause", "Ljava/lang/Throwable;");
3092 if (gDvm.classJavaLangObject == NULL)
3093 gDvm.classJavaLangObject =
3094 dvmFindSystemClassNoInit("Ljava/lang/Object;");
3096 if (meth->registersSize * insnsSize > 4*1024*1024) {
3098 "VFY: warning: method is huge (regs=%d insnsSize=%d)\n",
3099 meth->registersSize, insnsSize);
3100 /* might be bogus data, might be some huge generated method */
3104 * Create register lists, and initialize them to "Unknown". If we're
3105 * also going to create the register map, we need to retain the
3106 * register lists for a larger set of addresses.
3108 if (!initRegisterTable(meth, vdata->insnFlags, ®Table,
3109 generateRegisterMap ? kTrackRegsGcPoints : kTrackRegsBranches))
3112 vdata->addrRegs = NULL; /* don't set this until we need it */
3115 * Initialize the types of the registers that correspond to the
3116 * method arguments. We can determine this from the method signature.
3118 if (!setTypesFromSignature(meth, regTable.addrRegs[0], vdata->uninitMap))
3124 if (!doCodeVerification(meth, vdata->insnFlags, ®Table, vdata->uninitMap))
3128 * Generate a register map.
3130 if (generateRegisterMap) {
3131 vdata->addrRegs = regTable.addrRegs;
3133 RegisterMap* pMap = dvmGenerateRegisterMapV(vdata);
3136 * Tuck it into the Method struct. It will either get used
3137 * directly or, if we're in dexopt, will be packed up and
3138 * appended to the DEX file.
3140 dvmSetRegisterMap((Method*)meth, pMap);
3150 free(regTable.addrRegs);
3151 free(regTable.regAlloc);
3156 * Grind through the instructions.
3158 * The basic strategy is as outlined in v3 4.11.1.2: set the "changed" bit
3159 * on the first instruction, process it (setting additional "changed" bits),
3160 * and repeat until there are no more.
3163 * - (N/A) operand stack is always the same size
3164 * - operand stack [registers] contain the correct types of values
3165 * - local variables [registers] contain the correct types of values
3166 * - methods are invoked with the appropriate arguments
3167 * - fields are assigned using values of appropriate types
3168 * - opcodes have the correct type values in operand registers
3169 * - there is never an uninitialized class instance in a local variable in
3170 * code protected by an exception handler (operand stack is okay, because
3171 * the operand stack is discarded when an exception is thrown) [can't
3172 * know what's a local var w/o the debug info -- should fall out of
3176 * - execution cannot fall off the end of the code
3178 * (We also do many of the items described in the "static checks" sections,
3179 * because it's easier to do them here.)
3181 * We need an array of RegType values, one per register, for every
3182 * instruction. In theory this could become quite large -- up to several
3183 * megabytes for a monster function. For self-preservation we reject
3184 * anything that requires more than a certain amount of memory. (Typical
3185 * "large" should be on the order of 4K code units * 8 registers.) This
3186 * will likely have to be adjusted.
3189 * The spec forbids backward branches when there's an uninitialized reference
3190 * in a register. The idea is to prevent something like this:
3193 * new-instance r0, MyClass
3195 * if-eq rN, loop // once
3198 * This leaves us with two different instances, both allocated by the
3199 * same instruction, but only one is initialized. The scheme outlined in
3200 * v3 4.11.1.4 wouldn't catch this, so they work around it by preventing
3201 * backward branches. We achieve identical results without restricting
3202 * code reordering by specifying that you can't execute the new-instance
3203 * instruction if a register contains an uninitialized instance created
3204 * by that same instrutcion.
3206 static bool doCodeVerification(const Method* meth, InsnFlags* insnFlags,
3207 RegisterTable* regTable, UninitInstanceMap* uninitMap)
3209 const int insnsSize = dvmGetMethodInsnsSize(meth);
3210 RegType workRegs[meth->registersSize + kExtraRegs];
3211 bool result = false;
3212 bool debugVerbose = false;
3213 int insnIdx, startGuess;
3216 * Begin by marking the first instruction as "changed".
3218 dvmInsnSetChanged(insnFlags, 0, true);
3220 if (doVerboseLogging(meth)) {
3222 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3223 LOGI("Now verifying: %s.%s %s (ins=%d regs=%d)\n",
3224 meth->clazz->descriptor, meth->name, desc,
3225 meth->insSize, meth->registersSize);
3226 LOGI(" ------ [0 4 8 12 16 20 24 28 32 36\n");
3229 debugVerbose = true;
3230 gDebugVerbose = true;
3232 gDebugVerbose = false;
3238 * Continue until no instructions are marked "changed".
3242 * Find the first marked one. Use "startGuess" as a way to find
3245 for (insnIdx = startGuess; insnIdx < insnsSize; insnIdx++) {
3246 if (dvmInsnIsChanged(insnFlags, insnIdx))
3250 if (insnIdx == insnsSize) {
3251 if (startGuess != 0) {
3252 /* try again, starting from the top */
3256 /* all flags are clear */
3262 * We carry the working set of registers from instruction to
3263 * instruction. If this address can be the target of a branch
3264 * (or throw) instruction, or if we're skipping around chasing
3265 * "changed" flags, we need to load the set of registers from
3268 * Because we always prefer to continue on to the next instruction,
3269 * we should never have a situation where we have a stray
3270 * "changed" flag set on an instruction that isn't a branch target.
3272 if (dvmInsnIsBranchTarget(insnFlags, insnIdx)) {
3273 RegType* insnRegs = getRegisterLine(regTable, insnIdx);
3274 assert(insnRegs != NULL);
3275 copyRegisters(workRegs, insnRegs, meth->registersSize + kExtraRegs);
3278 dumpRegTypes(meth, insnFlags, workRegs, insnIdx, NULL,uninitMap,
3284 dumpRegTypes(meth, insnFlags, workRegs, insnIdx, NULL,uninitMap,
3290 * Sanity check: retrieve the stored register line (assuming
3291 * a full table) and make sure it actually matches.
3293 RegType* insnRegs = getRegisterLine(regTable, insnIdx);
3294 if (insnRegs != NULL &&
3295 compareRegisters(workRegs, insnRegs,
3296 meth->registersSize + kExtraRegs) != 0)
3298 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3299 LOG_VFY("HUH? workRegs diverged in %s.%s %s\n",
3300 meth->clazz->descriptor, meth->name, desc);
3302 dumpRegTypes(meth, insnFlags, workRegs, 0, "work",
3303 uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS);
3304 dumpRegTypes(meth, insnFlags, insnRegs, 0, "insn",
3305 uninitMap, DRT_SHOW_REF_TYPES | DRT_SHOW_LOCALS);
3310 //LOGI("process %s.%s %s %d\n",
3311 // meth->clazz->descriptor, meth->name, meth->descriptor, insnIdx);
3312 if (!verifyInstruction(meth, insnFlags, regTable, workRegs, insnIdx,
3313 uninitMap, &startGuess))
3315 //LOGD("+++ %s bailing at %d\n", meth->name, insnIdx);
3321 static const int gcMask = kInstrCanBranch | kInstrCanSwitch |
3322 kInstrCanThrow | kInstrCanReturn;
3323 OpCode opCode = *(meth->insns + insnIdx) & 0xff;
3324 int flags = dexGetInstrFlags(gDvm.instrFlags, opCode);
3326 /* 8, 16, 32, or 32*n -bit regs */
3327 int regWidth = (meth->registersSize + 7) / 8;
3331 regWidth = ((regWidth + 3) / 4) * 4;
3333 LOGW("WOW: %d regs -> %d %s.%s\n",
3334 meth->registersSize, regWidth,
3335 meth->clazz->descriptor, meth->name);
3340 if ((flags & gcMask) != 0) {
3341 /* this is a potential GC point */
3344 if (insnsSize < 256)
3348 gDvm__gcData += regWidth;
3350 gDvm__gcSimpleData += regWidth;
3357 * Clear "changed" and mark as visited.
3359 dvmInsnSetVisited(insnFlags, insnIdx, true);
3360 dvmInsnSetChanged(insnFlags, insnIdx, false);
3363 if (DEAD_CODE_SCAN && !IS_METHOD_FLAG_SET(meth, METHOD_ISWRITABLE)) {
3365 * Scan for dead code. There's nothing "evil" about dead code
3366 * (besides the wasted space), but it indicates a flaw somewhere
3367 * down the line, possibly in the verifier.
3369 * If we've rewritten "always throw" instructions into the stream,
3370 * we are almost certainly going to have some dead code.
3373 for (insnIdx = 0; insnIdx < insnsSize;
3374 insnIdx += dvmInsnGetWidth(insnFlags, insnIdx))
3377 * Switch-statement data doesn't get "visited" by scanner. It
3378 * may or may not be preceded by a padding NOP.
3380 int instr = meth->insns[insnIdx];
3381 if (instr == kPackedSwitchSignature ||
3382 instr == kSparseSwitchSignature ||
3383 instr == kArrayDataSignature ||
3385 (meth->insns[insnIdx+1] == kPackedSwitchSignature ||
3386 meth->insns[insnIdx+1] == kSparseSwitchSignature ||
3387 meth->insns[insnIdx+1] == kArrayDataSignature)))
3389 dvmInsnSetVisited(insnFlags, insnIdx, true);
3392 if (!dvmInsnIsVisited(insnFlags, insnIdx)) {
3394 deadStart = insnIdx;
3395 } else if (deadStart >= 0) {
3398 dexProtoCopyMethodDescriptor(&meth->prototype);
3399 LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s\n",
3400 deadStart, insnIdx-1,
3401 meth->clazz->descriptor, meth->name, desc);
3408 if (deadStart >= 0) {
3410 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
3411 LOGD("VFY: dead code 0x%04x-%04x in %s.%s %s\n",
3412 deadStart, insnIdx-1,
3413 meth->clazz->descriptor, meth->name, desc);
3427 * Perform verification for a single instruction.
3429 * This requires fully decoding the instruction to determine the effect
3430 * it has on registers.
3432 * Finds zero or more following instructions and sets the "changed" flag
3433 * if execution at that point needs to be (re-)evaluated. Register changes
3434 * are merged into "regTypes" at the target addresses. Does not set or
3435 * clear any other flags in "insnFlags".
3437 * This may alter meth->insns if we need to replace an instruction with
3438 * throw-verification-error.
3440 static bool verifyInstruction(const Method* meth, InsnFlags* insnFlags,
3441 RegisterTable* regTable, RegType* workRegs, int insnIdx,
3442 UninitInstanceMap* uninitMap, int* pStartGuess)
3444 const int insnsSize = dvmGetMethodInsnsSize(meth);
3445 const u2* insns = meth->insns + insnIdx;
3446 bool result = false;
3449 * Once we finish decoding the instruction, we need to figure out where
3450 * we can go from here. There are three possible ways to transfer
3451 * control to another statement:
3453 * (1) Continue to the next instruction. Applies to all but
3454 * unconditional branches, method returns, and exception throws.
3455 * (2) Branch to one or more possible locations. Applies to branches
3456 * and switch statements.
3457 * (3) Exception handlers. Applies to any instruction that can
3458 * throw an exception that is handled by an encompassing "try"
3461 * We can also return, in which case there is no successor instruction
3464 * The behavior can be determined from the InstructionFlags.
3467 const DexFile* pDexFile = meth->clazz->pDvmDex->pDexFile;
3468 RegType entryRegs[meth->registersSize + kExtraRegs];
3469 ClassObject* resClass;
3470 int branchTarget = 0;
3471 const int insnRegCount = meth->registersSize;
3473 DecodedInstruction decInsn;
3474 bool justSetResult = false;
3475 VerifyError failure = VERIFY_ERROR_NONE;
3478 memset(&decInsn, 0x81, sizeof(decInsn));
3480 dexDecodeInstruction(gDvm.instrFormat, insns, &decInsn);
3482 int nextFlags = dexGetInstrFlags(gDvm.instrFlags, decInsn.opCode);
3485 * Make a copy of the previous register state. If the instruction
3486 * throws an exception, we merge *this* into the destination rather
3487 * than workRegs, because we don't want the result from the "successful"
3488 * code path (e.g. a check-cast that "improves" a type) to be visible
3489 * to the exception handler.
3491 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
3493 copyRegisters(entryRegs, workRegs, meth->registersSize + kExtraRegs);
3496 memset(entryRegs, 0xdd,
3497 (meth->registersSize + kExtraRegs) * sizeof(RegType));
3501 switch (decInsn.opCode) {
3504 * A "pure" NOP has no effect on anything. Data tables start with
3505 * a signature that looks like a NOP; if we see one of these in
3506 * the course of executing code then we have a problem.
3508 if (decInsn.vA != 0) {
3509 LOG_VFY("VFY: encountered data table in instruction stream\n");
3510 failure = VERIFY_ERROR_GENERIC;
3515 case OP_MOVE_FROM16:
3517 copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
3518 kTypeCategory1nr, &failure);
3521 case OP_MOVE_WIDE_FROM16:
3522 case OP_MOVE_WIDE_16:
3523 copyRegister2(workRegs, insnRegCount, decInsn.vA, decInsn.vB, &failure);
3525 case OP_MOVE_OBJECT:
3526 case OP_MOVE_OBJECT_FROM16:
3527 case OP_MOVE_OBJECT_16:
3528 copyRegister1(workRegs, insnRegCount, decInsn.vA, decInsn.vB,
3529 kTypeCategoryRef, &failure);
3533 * The move-result instructions copy data out of a "pseudo-register"
3534 * with the results from the last method invocation. In practice we
3535 * might want to hold the result in an actual CPU register, so the
3536 * Dalvik spec requires that these only appear immediately after an
3537 * invoke or filled-new-array.
3539 * These calls invalidate the "result" register. (This is now
3540 * redundant with the reset done below, but it can make the debug info
3541 * easier to read in some cases.)
3543 case OP_MOVE_RESULT:
3544 copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
3545 kTypeCategory1nr, &failure);
3547 case OP_MOVE_RESULT_WIDE:
3548 copyResultRegister2(workRegs, insnRegCount, decInsn.vA, &failure);
3550 case OP_MOVE_RESULT_OBJECT:
3551 copyResultRegister1(workRegs, insnRegCount, decInsn.vA,
3552 kTypeCategoryRef, &failure);
3555 case OP_MOVE_EXCEPTION:
3557 * This statement can only appear as the first instruction in an
3558 * exception handler (though not all exception handlers need to
3559 * have one of these). We verify that as part of extracting the
3560 * exception type from the catch block list.
3562 * "resClass" will hold the closest common superclass of all
3563 * exceptions that can be handled here.
3565 resClass = getCaughtExceptionType(meth, insnIdx, &failure);
3566 if (resClass == NULL) {
3567 assert(!VERIFY_OK(failure));
3569 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3570 regTypeFromClass(resClass), &failure);
3574 case OP_RETURN_VOID:
3575 if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
3576 failure = VERIFY_ERROR_GENERIC;
3577 } else if (getMethodReturnType(meth) != kRegTypeUnknown) {
3578 LOG_VFY("VFY: return-void not expected\n");
3579 failure = VERIFY_ERROR_GENERIC;
3583 if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
3584 failure = VERIFY_ERROR_GENERIC;
3586 /* check the method signature */
3587 RegType returnType = getMethodReturnType(meth);
3588 checkTypeCategory(returnType, kTypeCategory1nr, &failure);
3589 if (!VERIFY_OK(failure))
3590 LOG_VFY("VFY: return-32 not expected\n");
3592 /* check the register contents */
3593 returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3595 checkTypeCategory(returnType, kTypeCategory1nr, &failure);
3596 if (!VERIFY_OK(failure))
3597 LOG_VFY("VFY: return-32 on invalid register v%d\n", decInsn.vA);
3600 case OP_RETURN_WIDE:
3601 if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
3602 failure = VERIFY_ERROR_GENERIC;
3604 RegType returnType, returnTypeHi;
3606 /* check the method signature */
3607 returnType = getMethodReturnType(meth);
3608 checkTypeCategory(returnType, kTypeCategory2, &failure);
3609 if (!VERIFY_OK(failure))
3610 LOG_VFY("VFY: return-wide not expected\n");
3612 /* check the register contents */
3613 returnType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3615 returnTypeHi = getRegisterType(workRegs, insnRegCount,
3616 decInsn.vA +1, &failure);
3617 if (VERIFY_OK(failure)) {
3618 checkTypeCategory(returnType, kTypeCategory2, &failure);
3619 checkWidePair(returnType, returnTypeHi, &failure);
3621 if (!VERIFY_OK(failure)) {
3622 LOG_VFY("VFY: return-wide on invalid register pair v%d\n",
3627 case OP_RETURN_OBJECT:
3628 if (!checkConstructorReturn(meth, workRegs, insnRegCount)) {
3629 failure = VERIFY_ERROR_GENERIC;
3631 RegType returnType = getMethodReturnType(meth);
3632 checkTypeCategory(returnType, kTypeCategoryRef, &failure);
3633 if (!VERIFY_OK(failure)) {
3634 LOG_VFY("VFY: return-object not expected\n");
3638 /* returnType is the *expected* return type, not register value */
3639 assert(returnType != kRegTypeZero);
3640 assert(!regTypeIsUninitReference(returnType));
3643 * Verify that the reference in vAA is an instance of the type
3644 * in "returnType". The Zero type is allowed here. If the
3645 * method is declared to return an interface, then any
3646 * initialized reference is acceptable.
3648 * Note getClassFromRegister fails if the register holds an
3649 * uninitialized reference, so we do not allow them to be
3652 ClassObject* declClass;
3654 declClass = regTypeInitializedReferenceToClass(returnType);
3655 resClass = getClassFromRegister(workRegs, insnRegCount,
3656 decInsn.vA, &failure);
3657 if (!VERIFY_OK(failure))
3659 if (resClass != NULL) {
3660 if (!dvmIsInterfaceClass(declClass) &&
3661 !dvmInstanceof(resClass, declClass))
3663 LOG_VFY("VFY: returning %s (cl=%p), declared %s (cl=%p)\n",
3664 resClass->descriptor, resClass->classLoader,
3665 declClass->descriptor, declClass->classLoader);
3666 failure = VERIFY_ERROR_GENERIC;
3676 /* could be boolean, int, float, or a null reference */
3677 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3678 dvmDetermineCat1Const((s4)decInsn.vB), &failure);
3680 case OP_CONST_HIGH16:
3681 /* could be boolean, int, float, or a null reference */
3682 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3683 dvmDetermineCat1Const((s4) decInsn.vB << 16), &failure);
3685 case OP_CONST_WIDE_16:
3686 case OP_CONST_WIDE_32:
3688 case OP_CONST_WIDE_HIGH16:
3689 /* could be long or double; default to long and allow conversion */
3690 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3691 kRegTypeLongLo, &failure);
3693 case OP_CONST_STRING:
3694 case OP_CONST_STRING_JUMBO:
3695 assert(gDvm.classJavaLangString != NULL);
3696 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3697 regTypeFromClass(gDvm.classJavaLangString), &failure);
3699 case OP_CONST_CLASS:
3700 assert(gDvm.classJavaLangClass != NULL);
3701 /* make sure we can resolve the class; access check is important */
3702 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
3703 if (resClass == NULL) {
3704 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3705 dvmLogUnableToResolveClass(badClassDesc, meth);
3706 LOG_VFY("VFY: unable to resolve const-class %d (%s) in %s\n",
3707 decInsn.vB, badClassDesc, meth->clazz->descriptor);
3708 assert(failure != VERIFY_ERROR_GENERIC);
3710 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3711 regTypeFromClass(gDvm.classJavaLangClass), &failure);
3715 case OP_MONITOR_ENTER:
3716 case OP_MONITOR_EXIT:
3717 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
3718 if (VERIFY_OK(failure)) {
3719 if (!regTypeIsReference(tmpType)) {
3720 LOG_VFY("VFY: monitor op on non-object\n");
3721 failure = VERIFY_ERROR_GENERIC;
3728 * If this instruction succeeds, we will promote register vA to
3729 * the type in vB. (This could be a demotion -- not expected, so
3730 * we don't try to address it.)
3732 * If it fails, an exception is thrown, which we deal with later
3733 * by ignoring the update to decInsn.vA when branching to a handler.
3735 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
3736 if (resClass == NULL) {
3737 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3738 dvmLogUnableToResolveClass(badClassDesc, meth);
3739 LOG_VFY("VFY: unable to resolve check-cast %d (%s) in %s\n",
3740 decInsn.vB, badClassDesc, meth->clazz->descriptor);
3741 assert(failure != VERIFY_ERROR_GENERIC);
3745 origType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
3747 if (!VERIFY_OK(failure))
3749 if (!regTypeIsReference(origType)) {
3750 LOG_VFY("VFY: check-cast on non-reference in v%u\n",decInsn.vA);
3751 failure = VERIFY_ERROR_GENERIC;
3754 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3755 regTypeFromClass(resClass), &failure);
3758 case OP_INSTANCE_OF:
3759 /* make sure we're checking a reference type */
3760 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
3761 if (!VERIFY_OK(failure))
3763 if (!regTypeIsReference(tmpType)) {
3764 LOG_VFY("VFY: vB not a reference (%d)\n", tmpType);
3765 failure = VERIFY_ERROR_GENERIC;
3769 /* make sure we can resolve the class; access check is important */
3770 resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
3771 if (resClass == NULL) {
3772 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
3773 dvmLogUnableToResolveClass(badClassDesc, meth);
3774 LOG_VFY("VFY: unable to resolve instanceof %d (%s) in %s\n",
3775 decInsn.vC, badClassDesc, meth->clazz->descriptor);
3776 assert(failure != VERIFY_ERROR_GENERIC);
3778 /* result is boolean */
3779 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3780 kRegTypeBoolean, &failure);
3784 case OP_ARRAY_LENGTH:
3785 resClass = getClassFromRegister(workRegs, insnRegCount,
3786 decInsn.vB, &failure);
3787 if (!VERIFY_OK(failure))
3789 if (resClass != NULL && !dvmIsArrayClass(resClass)) {
3790 LOG_VFY("VFY: array-length on non-array\n");
3791 failure = VERIFY_ERROR_GENERIC;
3794 setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeInteger,
3798 case OP_NEW_INSTANCE:
3799 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
3800 if (resClass == NULL) {
3801 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3802 dvmLogUnableToResolveClass(badClassDesc, meth);
3803 LOG_VFY("VFY: unable to resolve new-instance %d (%s) in %s\n",
3804 decInsn.vB, badClassDesc, meth->clazz->descriptor);
3805 assert(failure != VERIFY_ERROR_GENERIC);
3809 /* can't create an instance of an interface or abstract class */
3810 if (dvmIsAbstractClass(resClass) || dvmIsInterfaceClass(resClass)) {
3811 LOG_VFY("VFY: new-instance on interface or abstract class %s\n",
3812 resClass->descriptor);
3813 failure = VERIFY_ERROR_INSTANTIATION;
3817 /* add resolved class to uninit map if not already there */
3818 int uidx = dvmSetUninitInstance(uninitMap, insnIdx, resClass);
3820 uninitType = regTypeFromUninitIndex(uidx);
3823 * Any registers holding previous allocations from this address
3824 * that have not yet been initialized must be marked invalid.
3826 markUninitRefsAsInvalid(workRegs, insnRegCount, uninitMap,
3829 /* add the new uninitialized reference to the register ste */
3830 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3831 uninitType, &failure);
3835 resClass = dvmOptResolveClass(meth->clazz, decInsn.vC, &failure);
3836 if (resClass == NULL) {
3837 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vC);
3838 dvmLogUnableToResolveClass(badClassDesc, meth);
3839 LOG_VFY("VFY: unable to resolve new-array %d (%s) in %s\n",
3840 decInsn.vC, badClassDesc, meth->clazz->descriptor);
3841 assert(failure != VERIFY_ERROR_GENERIC);
3842 } else if (!dvmIsArrayClass(resClass)) {
3843 LOG_VFY("VFY: new-array on non-array class\n");
3844 failure = VERIFY_ERROR_GENERIC;
3846 /* make sure "size" register is valid type */
3847 verifyRegisterType(workRegs, insnRegCount, decInsn.vB,
3848 kRegTypeInteger, &failure);
3849 /* set register type to array class */
3850 setRegisterType(workRegs, insnRegCount, decInsn.vA,
3851 regTypeFromClass(resClass), &failure);
3854 case OP_FILLED_NEW_ARRAY:
3855 case OP_FILLED_NEW_ARRAY_RANGE:
3856 resClass = dvmOptResolveClass(meth->clazz, decInsn.vB, &failure);
3857 if (resClass == NULL) {
3858 const char* badClassDesc = dexStringByTypeIdx(pDexFile, decInsn.vB);
3859 dvmLogUnableToResolveClass(badClassDesc, meth);
3860 LOG_VFY("VFY: unable to resolve filled-array %d (%s) in %s\n",
3861 decInsn.vB, badClassDesc, meth->clazz->descriptor);
3862 assert(failure != VERIFY_ERROR_GENERIC);
3863 } else if (!dvmIsArrayClass(resClass)) {
3864 LOG_VFY("VFY: filled-new-array on non-array class\n");
3865 failure = VERIFY_ERROR_GENERIC;
3867 bool isRange = (decInsn.opCode == OP_FILLED_NEW_ARRAY_RANGE);
3869 /* check the arguments to the instruction */
3870 verifyFilledNewArrayRegs(meth, workRegs, insnRegCount, &decInsn,
3871 resClass, isRange, &failure);
3872 /* filled-array result goes into "result" register */
3873 setResultRegisterType(workRegs, insnRegCount,
3874 regTypeFromClass(resClass), &failure);
3875 justSetResult = true;
3881 verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeFloat,
3883 verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeFloat,
3885 setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
3888 case OP_CMPL_DOUBLE:
3889 case OP_CMPG_DOUBLE:
3890 verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeDoubleLo,
3892 verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeDoubleLo,
3894 setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
3898 verifyRegisterType(workRegs, insnRegCount, decInsn.vB, kRegTypeLongLo,
3900 verifyRegisterType(workRegs, insnRegCount, decInsn.vC, kRegTypeLongLo,
3902 setRegisterType(workRegs, insnRegCount, decInsn.vA, kRegTypeBoolean,
3907 resClass = getClassFromRegister(workRegs, insnRegCount,
3908 decInsn.vA, &failure);
3909 if (VERIFY_OK(failure) && resClass != NULL) {
3910 if (!dvmInstanceof(resClass, gDvm.classJavaLangThrowable)) {
3911 LOG_VFY("VFY: thrown class %s not instanceof Throwable\n",
3912 resClass->descriptor);
3913 failure = VERIFY_ERROR_GENERIC;
3921 /* no effect on or use of registers */
3924 case OP_PACKED_SWITCH:
3925 case OP_SPARSE_SWITCH:
3926 /* verify that vAA is an integer, or can be converted to one */
3927 verifyRegisterType(workRegs, insnRegCount, decInsn.vA,
3928 kRegTypeInteger, &failure);
3931 case OP_FILL_ARRAY_DATA:
3934 const u2 *arrayData;
3937 /* Similar to the verification done for APUT */
3938 resClass = getClassFromRegister(workRegs, insnRegCount,
3939 decInsn.vA, &failure);
3940 if (!VERIFY_OK(failure))
3943 /* resClass can be null if the reg type is Zero */
3944 if (resClass == NULL)
3947 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
3948 resClass->elementClass->primitiveType == PRIM_NOT ||
3949 resClass->elementClass->primitiveType == PRIM_VOID)
3951 LOG_VFY("VFY: invalid fill-array-data on %s\n",
3952 resClass->descriptor);
3953 failure = VERIFY_ERROR_GENERIC;
3957 valueType = primitiveTypeToRegType(
3958 resClass->elementClass->primitiveType);
3959 assert(valueType != kRegTypeUnknown);
3962 * Now verify if the element width in the table matches the element
3963 * width declared in the array
3965 arrayData = insns + (insns[1] | (((s4)insns[2]) << 16));
3966 if (arrayData[0] != kArrayDataSignature) {
3967 LOG_VFY("VFY: invalid magic for array-data\n");
3968 failure = VERIFY_ERROR_GENERIC;
3972 switch (resClass->elementClass->primitiveType) {
3995 * Since we don't compress the data in Dex, expect to see equal
3996 * width of data stored in the table and expected from the array
3999 if (arrayData[1] != elemWidth) {
4000 LOG_VFY("VFY: array-data size mismatch (%d vs %d)\n",
4001 arrayData[1], elemWidth);
4002 failure = VERIFY_ERROR_GENERIC;
4010 RegType type1, type2;
4012 type1 = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4014 type2 = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4016 if (!VERIFY_OK(failure))
4019 /* both references? */
4020 if (regTypeIsReference(type1) && regTypeIsReference(type2))
4023 /* both category-1nr? */
4024 checkTypeCategory(type1, kTypeCategory1nr, &failure);
4025 checkTypeCategory(type2, kTypeCategory1nr, &failure);
4026 if (!VERIFY_OK(failure)) {
4027 LOG_VFY("VFY: args to if-eq/if-ne must both be refs or cat1\n");
4036 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4037 if (!VERIFY_OK(failure))
4039 checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4040 if (!VERIFY_OK(failure)) {
4041 LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
4044 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vB, &failure);
4045 if (!VERIFY_OK(failure))
4047 checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4048 if (!VERIFY_OK(failure)) {
4049 LOG_VFY("VFY: args to 'if' must be cat-1nr\n");
4055 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4056 if (!VERIFY_OK(failure))
4058 if (regTypeIsReference(tmpType))
4060 checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4061 if (!VERIFY_OK(failure))
4062 LOG_VFY("VFY: expected cat-1 arg to if\n");
4068 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4069 if (!VERIFY_OK(failure))
4071 checkTypeCategory(tmpType, kTypeCategory1nr, &failure);
4072 if (!VERIFY_OK(failure))
4073 LOG_VFY("VFY: expected cat-1 arg to if\n");
4077 tmpType = kRegTypeInteger;
4078 goto aget_1nr_common;
4079 case OP_AGET_BOOLEAN:
4080 tmpType = kRegTypeBoolean;
4081 goto aget_1nr_common;
4083 tmpType = kRegTypeByte;
4084 goto aget_1nr_common;
4086 tmpType = kRegTypeChar;
4087 goto aget_1nr_common;
4089 tmpType = kRegTypeShort;
4090 goto aget_1nr_common;
4093 RegType srcType, indexType;
4095 indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4097 checkArrayIndexType(meth, indexType, &failure);
4098 if (!VERIFY_OK(failure))
4101 resClass = getClassFromRegister(workRegs, insnRegCount,
4102 decInsn.vB, &failure);
4103 if (!VERIFY_OK(failure))
4105 if (resClass != NULL) {
4106 /* verify the class */
4107 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4108 resClass->elementClass->primitiveType == PRIM_NOT)
4110 LOG_VFY("VFY: invalid aget-1nr target %s\n",
4111 resClass->descriptor);
4112 failure = VERIFY_ERROR_GENERIC;
4116 /* make sure array type matches instruction */
4117 srcType = primitiveTypeToRegType(
4118 resClass->elementClass->primitiveType);
4120 if (!checkFieldArrayStore1nr(tmpType, srcType)) {
4121 LOG_VFY("VFY: invalid aget-1nr, array type=%d with"
4122 " inst type=%d (on %s)\n",
4123 srcType, tmpType, resClass->descriptor);
4124 failure = VERIFY_ERROR_GENERIC;
4129 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4136 RegType dstType, indexType;
4138 indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4140 checkArrayIndexType(meth, indexType, &failure);
4141 if (!VERIFY_OK(failure))
4144 resClass = getClassFromRegister(workRegs, insnRegCount,
4145 decInsn.vB, &failure);
4146 if (!VERIFY_OK(failure))
4148 if (resClass != NULL) {
4149 /* verify the class */
4150 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4151 resClass->elementClass->primitiveType == PRIM_NOT)
4153 LOG_VFY("VFY: invalid aget-wide target %s\n",
4154 resClass->descriptor);
4155 failure = VERIFY_ERROR_GENERIC;
4159 /* try to refine "dstType" */
4160 switch (resClass->elementClass->primitiveType) {
4162 dstType = kRegTypeLongLo;
4165 dstType = kRegTypeDoubleLo;
4168 LOG_VFY("VFY: invalid aget-wide on %s\n",
4169 resClass->descriptor);
4170 dstType = kRegTypeUnknown;
4171 failure = VERIFY_ERROR_GENERIC;
4176 * Null array ref; this code path will fail at runtime. We
4177 * know this is either long or double, and we don't really
4178 * discriminate between those during verification, so we
4181 dstType = kRegTypeLongLo;
4183 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4188 case OP_AGET_OBJECT:
4190 RegType dstType, indexType;
4192 indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4194 checkArrayIndexType(meth, indexType, &failure);
4195 if (!VERIFY_OK(failure))
4198 /* get the class of the array we're pulling an object from */
4199 resClass = getClassFromRegister(workRegs, insnRegCount,
4200 decInsn.vB, &failure);
4201 if (!VERIFY_OK(failure))
4203 if (resClass != NULL) {
4204 ClassObject* elementClass;
4206 assert(resClass != NULL);
4207 if (!dvmIsArrayClass(resClass)) {
4208 LOG_VFY("VFY: aget-object on non-array class\n");
4209 failure = VERIFY_ERROR_GENERIC;
4212 assert(resClass->elementClass != NULL);
4215 * Find the element class. resClass->elementClass indicates
4216 * the basic type, which won't be what we want for a
4217 * multi-dimensional array.
4219 if (resClass->descriptor[1] == '[') {
4220 assert(resClass->arrayDim > 1);
4221 elementClass = dvmFindArrayClass(&resClass->descriptor[1],
4222 resClass->classLoader);
4223 } else if (resClass->descriptor[1] == 'L') {
4224 assert(resClass->arrayDim == 1);
4225 elementClass = resClass->elementClass;
4227 LOG_VFY("VFY: aget-object on non-ref array class (%s)\n",
4228 resClass->descriptor);
4229 failure = VERIFY_ERROR_GENERIC;
4233 dstType = regTypeFromClass(elementClass);
4236 * The array reference is NULL, so the current code path will
4237 * throw an exception. For proper merging with later code
4238 * paths, and correct handling of "if-eqz" tests on the
4239 * result of the array get, we want to treat this as a null
4242 dstType = kRegTypeZero;
4244 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4249 tmpType = kRegTypeInteger;
4250 goto aput_1nr_common;
4251 case OP_APUT_BOOLEAN:
4252 tmpType = kRegTypeBoolean;
4253 goto aput_1nr_common;
4255 tmpType = kRegTypeByte;
4256 goto aput_1nr_common;
4258 tmpType = kRegTypeChar;
4259 goto aput_1nr_common;
4261 tmpType = kRegTypeShort;
4262 goto aput_1nr_common;
4265 RegType srcType, dstType, indexType;
4267 indexType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4269 checkArrayIndexType(meth, indexType, &failure);
4270 if (!VERIFY_OK(failure))
4273 /* make sure the source register has the correct type */
4274 srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4276 if (!canConvertTo1nr(srcType, tmpType)) {
4277 LOG_VFY("VFY: invalid reg type %d on aput instr (need %d)\n",
4279 failure = VERIFY_ERROR_GENERIC;
4283 resClass = getClassFromRegister(workRegs, insnRegCount,
4284 decInsn.vB, &failure);
4285 if (!VERIFY_OK(failure))
4288 /* resClass can be null if the reg type is Zero */
4289 if (resClass == NULL)
4292 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4293 resClass->elementClass->primitiveType == PRIM_NOT)
4295 LOG_VFY("VFY: invalid aput-1nr on %s\n", resClass->descriptor);
4296 failure = VERIFY_ERROR_GENERIC;
4300 /* verify that instruction matches array */
4301 dstType = primitiveTypeToRegType(
4302 resClass->elementClass->primitiveType);
4303 assert(dstType != kRegTypeUnknown);
4305 if (!checkFieldArrayStore1nr(tmpType, dstType)) {
4306 LOG_VFY("VFY: invalid aput-1nr on %s (inst=%d dst=%d)\n",
4307 resClass->descriptor, tmpType, dstType);
4308 failure = VERIFY_ERROR_GENERIC;
4314 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4316 checkArrayIndexType(meth, tmpType, &failure);
4317 if (!VERIFY_OK(failure))
4320 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4321 if (VERIFY_OK(failure)) {
4323 getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
4324 checkTypeCategory(tmpType, kTypeCategory2, &failure);
4325 checkWidePair(tmpType, typeHi, &failure);
4327 if (!VERIFY_OK(failure))
4330 resClass = getClassFromRegister(workRegs, insnRegCount,
4331 decInsn.vB, &failure);
4332 if (!VERIFY_OK(failure))
4334 if (resClass != NULL) {
4335 /* verify the class and try to refine "dstType" */
4336 if (!dvmIsArrayClass(resClass) || resClass->arrayDim != 1 ||
4337 resClass->elementClass->primitiveType == PRIM_NOT)
4339 LOG_VFY("VFY: invalid aput-wide on %s\n",
4340 resClass->descriptor);
4341 failure = VERIFY_ERROR_GENERIC;
4345 switch (resClass->elementClass->primitiveType) {
4348 /* these are okay */
4351 LOG_VFY("VFY: invalid aput-wide on %s\n",
4352 resClass->descriptor);
4353 failure = VERIFY_ERROR_GENERIC;
4358 case OP_APUT_OBJECT:
4359 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vC,
4361 checkArrayIndexType(meth, tmpType, &failure);
4362 if (!VERIFY_OK(failure))
4365 /* get the ref we're storing; Zero is okay, Uninit is not */
4366 resClass = getClassFromRegister(workRegs, insnRegCount,
4367 decInsn.vA, &failure);
4368 if (!VERIFY_OK(failure))
4370 if (resClass != NULL) {
4371 ClassObject* arrayClass;
4372 ClassObject* elementClass;
4375 * Get the array class. If the array ref is null, we won't
4376 * have type information (and we'll crash at runtime with a
4377 * null pointer exception).
4379 arrayClass = getClassFromRegister(workRegs, insnRegCount,
4380 decInsn.vB, &failure);
4382 if (arrayClass != NULL) {
4383 /* see if the array holds a compatible type */
4384 if (!dvmIsArrayClass(arrayClass)) {
4385 LOG_VFY("VFY: invalid aput-object on %s\n",
4386 arrayClass->descriptor);
4387 failure = VERIFY_ERROR_GENERIC;
4392 * Find the element class. resClass->elementClass indicates
4393 * the basic type, which won't be what we want for a
4394 * multi-dimensional array.
4396 * All we want to check here is that the element type is a
4397 * reference class. We *don't* check instanceof here, because
4398 * you can still put a String into a String[] after the latter
4399 * has been cast to an Object[].
4401 if (arrayClass->descriptor[1] == '[') {
4402 assert(arrayClass->arrayDim > 1);
4403 elementClass = dvmFindArrayClass(&arrayClass->descriptor[1],
4404 arrayClass->classLoader);
4406 assert(arrayClass->arrayDim == 1);
4407 elementClass = arrayClass->elementClass;
4409 if (elementClass->primitiveType != PRIM_NOT) {
4410 LOG_VFY("VFY: invalid aput-object of %s into %s\n",
4411 resClass->descriptor, arrayClass->descriptor);
4412 failure = VERIFY_ERROR_GENERIC;
4420 case OP_IGET_VOLATILE:
4421 tmpType = kRegTypeInteger;
4422 goto iget_1nr_common;
4423 case OP_IGET_BOOLEAN:
4424 tmpType = kRegTypeBoolean;
4425 goto iget_1nr_common;
4427 tmpType = kRegTypeByte;
4428 goto iget_1nr_common;
4430 tmpType = kRegTypeChar;
4431 goto iget_1nr_common;
4433 tmpType = kRegTypeShort;
4434 goto iget_1nr_common;
4437 InstField* instField;
4438 RegType objType, fieldType;
4440 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4442 if (!VERIFY_OK(failure))
4444 instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4446 if (!VERIFY_OK(failure))
4449 /* make sure the field's type is compatible with expectation */
4450 fieldType = primSigCharToRegType(instField->field.signature[0]);
4451 if (fieldType == kRegTypeUnknown ||
4452 !checkFieldArrayStore1nr(tmpType, fieldType))
4454 LOG_VFY("VFY: invalid iget-1nr of %s.%s (inst=%d field=%d)\n",
4455 instField->field.clazz->descriptor,
4456 instField->field.name, tmpType, fieldType);
4457 failure = VERIFY_ERROR_GENERIC;
4461 setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
4466 case OP_IGET_WIDE_VOLATILE:
4469 InstField* instField;
4472 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4474 if (!VERIFY_OK(failure))
4476 instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4478 if (!VERIFY_OK(failure))
4480 /* check the type, which should be prim */
4481 switch (instField->field.signature[0]) {
4483 dstType = kRegTypeDoubleLo;
4486 dstType = kRegTypeLongLo;
4489 LOG_VFY("VFY: invalid iget-wide of %s.%s\n",
4490 instField->field.clazz->descriptor,
4491 instField->field.name);
4492 dstType = kRegTypeUnknown;
4493 failure = VERIFY_ERROR_GENERIC;
4496 if (VERIFY_OK(failure)) {
4497 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4502 case OP_IGET_OBJECT:
4503 case OP_IGET_OBJECT_VOLATILE:
4505 ClassObject* fieldClass;
4506 InstField* instField;
4509 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4511 if (!VERIFY_OK(failure))
4513 instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4515 if (!VERIFY_OK(failure))
4517 fieldClass = getFieldClass(meth, &instField->field);
4518 if (fieldClass == NULL) {
4519 /* class not found or primitive type */
4520 LOG_VFY("VFY: unable to recover field class from '%s'\n",
4521 instField->field.signature);
4522 failure = VERIFY_ERROR_GENERIC;
4525 if (VERIFY_OK(failure)) {
4526 assert(!dvmIsPrimitiveClass(fieldClass));
4527 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4528 regTypeFromClass(fieldClass), &failure);
4533 case OP_IPUT_VOLATILE:
4534 tmpType = kRegTypeInteger;
4535 goto iput_1nr_common;
4536 case OP_IPUT_BOOLEAN:
4537 tmpType = kRegTypeBoolean;
4538 goto iput_1nr_common;
4540 tmpType = kRegTypeByte;
4541 goto iput_1nr_common;
4543 tmpType = kRegTypeChar;
4544 goto iput_1nr_common;
4546 tmpType = kRegTypeShort;
4547 goto iput_1nr_common;
4550 RegType srcType, fieldType, objType;
4551 InstField* instField;
4553 srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4557 * javac generates synthetic functions that write byte values
4558 * into boolean fields.
4560 if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte)
4561 srcType = kRegTypeBoolean;
4563 /* make sure the source register has the correct type */
4564 if (!canConvertTo1nr(srcType, tmpType)) {
4565 LOG_VFY("VFY: invalid reg type %d on iput instr (need %d)\n",
4567 failure = VERIFY_ERROR_GENERIC;
4571 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4573 if (!VERIFY_OK(failure))
4575 instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4577 if (!VERIFY_OK(failure))
4579 checkFinalFieldAccess(meth, &instField->field, &failure);
4580 if (!VERIFY_OK(failure))
4583 /* get type of field we're storing into */
4584 fieldType = primSigCharToRegType(instField->field.signature[0]);
4585 if (fieldType == kRegTypeUnknown ||
4586 !checkFieldArrayStore1nr(tmpType, fieldType))
4588 LOG_VFY("VFY: invalid iput-1nr of %s.%s (inst=%d field=%d)\n",
4589 instField->field.clazz->descriptor,
4590 instField->field.name, tmpType, fieldType);
4591 failure = VERIFY_ERROR_GENERIC;
4597 case OP_IPUT_WIDE_VOLATILE:
4598 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4599 if (VERIFY_OK(failure)) {
4601 getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
4602 checkTypeCategory(tmpType, kTypeCategory2, &failure);
4603 checkWidePair(tmpType, typeHi, &failure);
4605 if (VERIFY_OK(failure)) {
4606 InstField* instField;
4609 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4611 if (!VERIFY_OK(failure))
4613 instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4615 if (!VERIFY_OK(failure))
4617 checkFinalFieldAccess(meth, &instField->field, &failure);
4618 if (!VERIFY_OK(failure))
4621 /* check the type, which should be prim */
4622 switch (instField->field.signature[0]) {
4625 /* these are okay (and interchangeable) */
4628 LOG_VFY("VFY: invalid iput-wide of %s.%s\n",
4629 instField->field.clazz->descriptor,
4630 instField->field.name);
4631 failure = VERIFY_ERROR_GENERIC;
4636 case OP_IPUT_OBJECT:
4637 case OP_IPUT_OBJECT_VOLATILE:
4639 ClassObject* fieldClass;
4640 ClassObject* valueClass;
4641 InstField* instField;
4642 RegType objType, valueType;
4644 objType = getRegisterType(workRegs, insnRegCount, decInsn.vB,
4646 if (!VERIFY_OK(failure))
4648 instField = getInstField(meth, uninitMap, objType, decInsn.vC,
4650 if (!VERIFY_OK(failure))
4652 checkFinalFieldAccess(meth, &instField->field, &failure);
4653 if (!VERIFY_OK(failure))
4656 fieldClass = getFieldClass(meth, &instField->field);
4657 if (fieldClass == NULL) {
4658 LOG_VFY("VFY: unable to recover field class from '%s'\n",
4659 instField->field.signature);
4660 failure = VERIFY_ERROR_GENERIC;
4664 valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4666 if (!VERIFY_OK(failure))
4668 if (!regTypeIsReference(valueType)) {
4669 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
4670 decInsn.vA, instField->field.name,
4671 fieldClass->descriptor);
4672 failure = VERIFY_ERROR_GENERIC;
4675 if (valueType != kRegTypeZero) {
4676 valueClass = regTypeInitializedReferenceToClass(valueType);
4677 if (valueClass == NULL) {
4678 LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
4680 failure = VERIFY_ERROR_GENERIC;
4683 /* allow if field is any interface or field is base class */
4684 if (!dvmIsInterfaceClass(fieldClass) &&
4685 !dvmInstanceof(valueClass, fieldClass))
4687 LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)\n",
4688 valueClass->descriptor, fieldClass->descriptor,
4689 instField->field.clazz->descriptor,
4690 instField->field.name);
4691 failure = VERIFY_ERROR_GENERIC;
4699 case OP_SGET_VOLATILE:
4700 tmpType = kRegTypeInteger;
4701 goto sget_1nr_common;
4702 case OP_SGET_BOOLEAN:
4703 tmpType = kRegTypeBoolean;
4704 goto sget_1nr_common;
4706 tmpType = kRegTypeByte;
4707 goto sget_1nr_common;
4709 tmpType = kRegTypeChar;
4710 goto sget_1nr_common;
4712 tmpType = kRegTypeShort;
4713 goto sget_1nr_common;
4716 StaticField* staticField;
4719 staticField = getStaticField(meth, decInsn.vB, &failure);
4720 if (!VERIFY_OK(failure))
4724 * Make sure the field's type is compatible with expectation.
4725 * We can get ourselves into trouble if we mix & match loads
4726 * and stores with different widths, so rather than just checking
4727 * "canConvertTo1nr" we require that the field types have equal
4728 * widths. (We can't generally require an exact type match,
4729 * because e.g. "int" and "float" are interchangeable.)
4731 fieldType = primSigCharToRegType(staticField->field.signature[0]);
4732 if (!checkFieldArrayStore1nr(tmpType, fieldType)) {
4733 LOG_VFY("VFY: invalid sget-1nr of %s.%s (inst=%d actual=%d)\n",
4734 staticField->field.clazz->descriptor,
4735 staticField->field.name, tmpType, fieldType);
4736 failure = VERIFY_ERROR_GENERIC;
4740 setRegisterType(workRegs, insnRegCount, decInsn.vA, tmpType,
4745 case OP_SGET_WIDE_VOLATILE:
4747 StaticField* staticField;
4750 staticField = getStaticField(meth, decInsn.vB, &failure);
4751 if (!VERIFY_OK(failure))
4753 /* check the type, which should be prim */
4754 switch (staticField->field.signature[0]) {
4756 dstType = kRegTypeDoubleLo;
4759 dstType = kRegTypeLongLo;
4762 LOG_VFY("VFY: invalid sget-wide of %s.%s\n",
4763 staticField->field.clazz->descriptor,
4764 staticField->field.name);
4765 dstType = kRegTypeUnknown;
4766 failure = VERIFY_ERROR_GENERIC;
4769 if (VERIFY_OK(failure)) {
4770 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4775 case OP_SGET_OBJECT:
4776 case OP_SGET_OBJECT_VOLATILE:
4778 StaticField* staticField;
4779 ClassObject* fieldClass;
4781 staticField = getStaticField(meth, decInsn.vB, &failure);
4782 if (!VERIFY_OK(failure))
4784 fieldClass = getFieldClass(meth, &staticField->field);
4785 if (fieldClass == NULL) {
4786 LOG_VFY("VFY: unable to recover field class from '%s'\n",
4787 staticField->field.signature);
4788 failure = VERIFY_ERROR_GENERIC;
4791 if (dvmIsPrimitiveClass(fieldClass)) {
4792 LOG_VFY("VFY: attempt to get prim field with sget-object\n");
4793 failure = VERIFY_ERROR_GENERIC;
4796 setRegisterType(workRegs, insnRegCount, decInsn.vA,
4797 regTypeFromClass(fieldClass), &failure);
4801 case OP_SPUT_VOLATILE:
4802 tmpType = kRegTypeInteger;
4803 goto sput_1nr_common;
4804 case OP_SPUT_BOOLEAN:
4805 tmpType = kRegTypeBoolean;
4806 goto sput_1nr_common;
4808 tmpType = kRegTypeByte;
4809 goto sput_1nr_common;
4811 tmpType = kRegTypeChar;
4812 goto sput_1nr_common;
4814 tmpType = kRegTypeShort;
4815 goto sput_1nr_common;
4818 RegType srcType, fieldType;
4819 StaticField* staticField;
4821 srcType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4825 * javac generates synthetic functions that write byte values
4826 * into boolean fields.
4828 if (tmpType == kRegTypeBoolean && srcType == kRegTypeByte)
4829 srcType = kRegTypeBoolean;
4831 /* make sure the source register has the correct type */
4832 if (!canConvertTo1nr(srcType, tmpType)) {
4833 LOG_VFY("VFY: invalid reg type %d on sput instr (need %d)\n",
4835 failure = VERIFY_ERROR_GENERIC;
4839 staticField = getStaticField(meth, decInsn.vB, &failure);
4840 if (!VERIFY_OK(failure))
4842 checkFinalFieldAccess(meth, &staticField->field, &failure);
4843 if (!VERIFY_OK(failure))
4847 * Get type of field we're storing into. We know that the
4848 * contents of the register match the instruction, but we also
4849 * need to ensure that the instruction matches the field type.
4850 * Using e.g. sput-short to write into a 32-bit integer field
4851 * can lead to trouble if we do 16-bit writes.
4853 fieldType = primSigCharToRegType(staticField->field.signature[0]);
4854 if (!checkFieldArrayStore1nr(tmpType, fieldType)) {
4855 LOG_VFY("VFY: invalid sput-1nr of %s.%s (inst=%d actual=%d)\n",
4856 staticField->field.clazz->descriptor,
4857 staticField->field.name, tmpType, fieldType);
4858 failure = VERIFY_ERROR_GENERIC;
4864 case OP_SPUT_WIDE_VOLATILE:
4865 tmpType = getRegisterType(workRegs, insnRegCount, decInsn.vA, &failure);
4866 if (VERIFY_OK(failure)) {
4868 getRegisterType(workRegs, insnRegCount, decInsn.vA+1, &failure);
4869 checkTypeCategory(tmpType, kTypeCategory2, &failure);
4870 checkWidePair(tmpType, typeHi, &failure);
4872 if (VERIFY_OK(failure)) {
4873 StaticField* staticField;
4875 staticField = getStaticField(meth, decInsn.vB, &failure);
4876 if (!VERIFY_OK(failure))
4878 checkFinalFieldAccess(meth, &staticField->field, &failure);
4879 if (!VERIFY_OK(failure))
4882 /* check the type, which should be prim */
4883 switch (staticField->field.signature[0]) {
4886 /* these are okay */
4889 LOG_VFY("VFY: invalid sput-wide of %s.%s\n",
4890 staticField->field.clazz->descriptor,
4891 staticField->field.name);
4892 failure = VERIFY_ERROR_GENERIC;
4897 case OP_SPUT_OBJECT:
4898 case OP_SPUT_OBJECT_VOLATILE:
4900 ClassObject* fieldClass;
4901 ClassObject* valueClass;
4902 StaticField* staticField;
4905 staticField = getStaticField(meth, decInsn.vB, &failure);
4906 if (!VERIFY_OK(failure))
4908 checkFinalFieldAccess(meth, &staticField->field, &failure);
4909 if (!VERIFY_OK(failure))
4912 fieldClass = getFieldClass(meth, &staticField->field);
4913 if (fieldClass == NULL) {
4914 LOG_VFY("VFY: unable to recover field class from '%s'\n",
4915 staticField->field.signature);
4916 failure = VERIFY_ERROR_GENERIC;
4920 valueType = getRegisterType(workRegs, insnRegCount, decInsn.vA,
4922 if (!VERIFY_OK(failure))
4924 if (!regTypeIsReference(valueType)) {
4925 LOG_VFY("VFY: storing non-ref v%d into ref field '%s' (%s)\n",
4926 decInsn.vA, staticField->field.name,
4927 fieldClass->descriptor);
4928 failure = VERIFY_ERROR_GENERIC;
4931 if (valueType != kRegTypeZero) {
4932 valueClass = regTypeInitializedReferenceToClass(valueType);
4933 if (valueClass == NULL) {
4934 LOG_VFY("VFY: storing uninit ref v%d into ref field\n",
4936 failure = VERIFY_ERROR_GENERIC;
4939 /* allow if field is any interface or field is base class */
4940 if (!dvmIsInterfaceClass(fieldClass) &&
4941 !dvmInstanceof(valueClass, fieldClass))
4943 LOG_VFY("VFY: storing type '%s' into field type '%s' (%s.%s)\n",
4944 valueClass->descriptor, fieldClass->descriptor,
4945 staticField->field.clazz->descriptor,
4946 staticField->field.name);
4947 failure = VERIFY_ERROR_GENERIC;
4954 case OP_INVOKE_VIRTUAL:
4955 case OP_INVOKE_VIRTUAL_RANGE:
4956 case OP_INVOKE_SUPER:
4957 case OP_INVOKE_SUPER_RANGE:
4959 Method* calledMethod;
4964 isRange = (decInsn.opCode == OP_INVOKE_VIRTUAL_RANGE ||
4965 decInsn.opCode == OP_INVOKE_SUPER_RANGE);
4966 isSuper = (decInsn.opCode == OP_INVOKE_SUPER ||
4967 decInsn.opCode == OP_INVOKE_SUPER_RANGE);
4969 calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
4970 &decInsn, uninitMap, METHOD_VIRTUAL, isRange,
4972 if (!VERIFY_OK(failure))
4974 returnType = getMethodReturnType(calledMethod);
4975 setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
4976 justSetResult = true;
4979 case OP_INVOKE_DIRECT:
4980 case OP_INVOKE_DIRECT_RANGE:
4983 Method* calledMethod;
4986 isRange = (decInsn.opCode == OP_INVOKE_DIRECT_RANGE);
4987 calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
4988 &decInsn, uninitMap, METHOD_DIRECT, isRange,
4990 if (!VERIFY_OK(failure))
4994 * Some additional checks when calling <init>. We know from
4995 * the invocation arg check that the "this" argument is an
4996 * instance of calledMethod->clazz. Now we further restrict
4997 * that to require that calledMethod->clazz is the same as
4998 * this->clazz or this->super, allowing the latter only if
4999 * the "this" argument is the same as the "this" argument to
5000 * this method (which implies that we're in <init> ourselves).
5002 if (isInitMethod(calledMethod)) {
5004 thisType = getInvocationThis(workRegs, insnRegCount,
5005 &decInsn, &failure);
5006 if (!VERIFY_OK(failure))
5009 /* no null refs allowed (?) */
5010 if (thisType == kRegTypeZero) {
5011 LOG_VFY("VFY: unable to initialize null ref\n");
5012 failure = VERIFY_ERROR_GENERIC;
5016 ClassObject* thisClass;
5018 thisClass = regTypeReferenceToClass(thisType, uninitMap);
5019 assert(thisClass != NULL);
5021 /* must be in same class or in superclass */
5022 if (calledMethod->clazz == thisClass->super) {
5023 if (thisClass != meth->clazz) {
5024 LOG_VFY("VFY: invoke-direct <init> on super only "
5025 "allowed for 'this' in <init>");
5026 failure = VERIFY_ERROR_GENERIC;
5029 } else if (calledMethod->clazz != thisClass) {
5030 LOG_VFY("VFY: invoke-direct <init> must be on current "
5031 "class or super\n");
5032 failure = VERIFY_ERROR_GENERIC;
5036 /* arg must be an uninitialized reference */
5037 if (!regTypeIsUninitReference(thisType)) {
5038 LOG_VFY("VFY: can only initialize the uninitialized\n");
5039 failure = VERIFY_ERROR_GENERIC;
5044 * Replace the uninitialized reference with an initialized
5045 * one, and clear the entry in the uninit map. We need to
5046 * do this for all registers that have the same object
5047 * instance in them, not just the "this" register.
5049 markRefsAsInitialized(workRegs, insnRegCount, uninitMap,
5050 thisType, &failure);
5051 if (!VERIFY_OK(failure))
5054 returnType = getMethodReturnType(calledMethod);
5055 setResultRegisterType(workRegs, insnRegCount,
5056 returnType, &failure);
5057 justSetResult = true;
5060 case OP_INVOKE_STATIC:
5061 case OP_INVOKE_STATIC_RANGE:
5064 Method* calledMethod;
5067 isRange = (decInsn.opCode == OP_INVOKE_STATIC_RANGE);
5068 calledMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
5069 &decInsn, uninitMap, METHOD_STATIC, isRange,
5071 if (!VERIFY_OK(failure))
5074 returnType = getMethodReturnType(calledMethod);
5075 setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
5076 justSetResult = true;
5079 case OP_INVOKE_INTERFACE:
5080 case OP_INVOKE_INTERFACE_RANGE:
5082 RegType /*thisType,*/ returnType;
5086 isRange = (decInsn.opCode == OP_INVOKE_INTERFACE_RANGE);
5087 absMethod = verifyInvocationArgs(meth, workRegs, insnRegCount,
5088 &decInsn, uninitMap, METHOD_INTERFACE, isRange,
5090 if (!VERIFY_OK(failure))
5093 #if 0 /* can't do this here, fails on dalvik test 052-verifier-fun */
5095 * Get the type of the "this" arg, which should always be an
5096 * interface class. Because we don't do a full merge on
5097 * interface classes, this might have reduced to Object.
5099 thisType = getInvocationThis(workRegs, insnRegCount,
5100 &decInsn, &failure);
5101 if (!VERIFY_OK(failure))
5104 if (thisType == kRegTypeZero) {
5105 /* null pointer always passes (and always fails at runtime) */
5107 ClassObject* thisClass;
5109 thisClass = regTypeInitializedReferenceToClass(thisType);
5110 if (thisClass == NULL) {
5111 LOG_VFY("VFY: interface call on uninitialized\n");
5112 failure = VERIFY_ERROR_GENERIC;
5117 * Either "thisClass" needs to be the interface class that
5118 * defined absMethod, or absMethod's class needs to be one
5119 * of the interfaces implemented by "thisClass". (Or, if
5120 * we couldn't complete the merge, this will be Object.)
5122 if (thisClass != absMethod->clazz &&
5123 thisClass != gDvm.classJavaLangObject &&
5124 !dvmImplements(thisClass, absMethod->clazz))
5126 LOG_VFY("VFY: unable to match absMethod '%s' with %s interfaces\n",
5127 absMethod->name, thisClass->descriptor);
5128 failure = VERIFY_ERROR_GENERIC;
5135 * We don't have an object instance, so we can't find the
5136 * concrete method. However, all of the type information is
5137 * in the abstract method, so we're good.
5139 returnType = getMethodReturnType(absMethod);
5140 setResultRegisterType(workRegs, insnRegCount, returnType, &failure);
5141 justSetResult = true;
5147 checkUnop(workRegs, insnRegCount, &decInsn,
5148 kRegTypeInteger, kRegTypeInteger, &failure);
5152 checkUnop(workRegs, insnRegCount, &decInsn,
5153 kRegTypeLongLo, kRegTypeLongLo, &failure);
5156 checkUnop(workRegs, insnRegCount, &decInsn,
5157 kRegTypeFloat, kRegTypeFloat, &failure);
5160 checkUnop(workRegs, insnRegCount, &decInsn,
5161 kRegTypeDoubleLo, kRegTypeDoubleLo, &failure);
5163 case OP_INT_TO_LONG:
5164 checkUnop(workRegs, insnRegCount, &decInsn,
5165 kRegTypeLongLo, kRegTypeInteger, &failure);
5167 case OP_INT_TO_FLOAT:
5168 checkUnop(workRegs, insnRegCount, &decInsn,
5169 kRegTypeFloat, kRegTypeInteger, &failure);
5171 case OP_INT_TO_DOUBLE:
5172 checkUnop(workRegs, insnRegCount, &decInsn,
5173 kRegTypeDoubleLo, kRegTypeInteger, &failure);
5175 case OP_LONG_TO_INT:
5176 checkUnop(workRegs, insnRegCount, &decInsn,
5177 kRegTypeInteger, kRegTypeLongLo, &failure);
5179 case OP_LONG_TO_FLOAT:
5180 checkUnop(workRegs, insnRegCount, &decInsn,
5181 kRegTypeFloat, kRegTypeLongLo, &failure);
5183 case OP_LONG_TO_DOUBLE:
5184 checkUnop(workRegs, insnRegCount, &decInsn,
5185 kRegTypeDoubleLo, kRegTypeLongLo, &failure);
5187 case OP_FLOAT_TO_INT:
5188 checkUnop(workRegs, insnRegCount, &decInsn,
5189 kRegTypeInteger, kRegTypeFloat, &failure);
5191 case OP_FLOAT_TO_LONG:
5192 checkUnop(workRegs, insnRegCount, &decInsn,
5193 kRegTypeLongLo, kRegTypeFloat, &failure);
5195 case OP_FLOAT_TO_DOUBLE:
5196 checkUnop(workRegs, insnRegCount, &decInsn,
5197 kRegTypeDoubleLo, kRegTypeFloat, &failure);
5199 case OP_DOUBLE_TO_INT:
5200 checkUnop(workRegs, insnRegCount, &decInsn,
5201 kRegTypeInteger, kRegTypeDoubleLo, &failure);
5203 case OP_DOUBLE_TO_LONG:
5204 checkUnop(workRegs, insnRegCount, &decInsn,
5205 kRegTypeLongLo, kRegTypeDoubleLo, &failure);
5207 case OP_DOUBLE_TO_FLOAT:
5208 checkUnop(workRegs, insnRegCount, &decInsn,
5209 kRegTypeFloat, kRegTypeDoubleLo, &failure);
5211 case OP_INT_TO_BYTE:
5212 checkUnop(workRegs, insnRegCount, &decInsn,
5213 kRegTypeByte, kRegTypeInteger, &failure);
5215 case OP_INT_TO_CHAR:
5216 checkUnop(workRegs, insnRegCount, &decInsn,
5217 kRegTypeChar, kRegTypeInteger, &failure);
5219 case OP_INT_TO_SHORT:
5220 checkUnop(workRegs, insnRegCount, &decInsn,
5221 kRegTypeShort, kRegTypeInteger, &failure);
5232 checkBinop(workRegs, insnRegCount, &decInsn,
5233 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
5238 checkBinop(workRegs, insnRegCount, &decInsn,
5239 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
5249 checkBinop(workRegs, insnRegCount, &decInsn,
5250 kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
5255 /* shift distance is Int, making these different from other binops */
5256 checkBinop(workRegs, insnRegCount, &decInsn,
5257 kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
5264 checkBinop(workRegs, insnRegCount, &decInsn,
5265 kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
5272 checkBinop(workRegs, insnRegCount, &decInsn,
5273 kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
5276 case OP_ADD_INT_2ADDR:
5277 case OP_SUB_INT_2ADDR:
5278 case OP_MUL_INT_2ADDR:
5279 case OP_REM_INT_2ADDR:
5280 case OP_SHL_INT_2ADDR:
5281 case OP_SHR_INT_2ADDR:
5282 case OP_USHR_INT_2ADDR:
5283 checkBinop2addr(workRegs, insnRegCount, &decInsn,
5284 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
5286 case OP_AND_INT_2ADDR:
5287 case OP_OR_INT_2ADDR:
5288 case OP_XOR_INT_2ADDR:
5289 checkBinop2addr(workRegs, insnRegCount, &decInsn,
5290 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, true, &failure);
5292 case OP_DIV_INT_2ADDR:
5293 checkBinop2addr(workRegs, insnRegCount, &decInsn,
5294 kRegTypeInteger, kRegTypeInteger, kRegTypeInteger, false, &failure);
5296 case OP_ADD_LONG_2ADDR:
5297 case OP_SUB_LONG_2ADDR:
5298 case OP_MUL_LONG_2ADDR:
5299 case OP_DIV_LONG_2ADDR:
5300 case OP_REM_LONG_2ADDR:
5301 case OP_AND_LONG_2ADDR:
5302 case OP_OR_LONG_2ADDR:
5303 case OP_XOR_LONG_2ADDR:
5304 checkBinop2addr(workRegs, insnRegCount, &decInsn,
5305 kRegTypeLongLo, kRegTypeLongLo, kRegTypeLongLo, false, &failure);
5307 case OP_SHL_LONG_2ADDR:
5308 case OP_SHR_LONG_2ADDR:
5309 case OP_USHR_LONG_2ADDR:
5310 checkBinop2addr(workRegs, insnRegCount, &decInsn,
5311 kRegTypeLongLo, kRegTypeLongLo, kRegTypeInteger, false, &failure);
5313 case OP_ADD_FLOAT_2ADDR:
5314 case OP_SUB_FLOAT_2ADDR:
5315 case OP_MUL_FLOAT_2ADDR:
5316 case OP_DIV_FLOAT_2ADDR:
5317 case OP_REM_FLOAT_2ADDR:
5318 checkBinop2addr(workRegs, insnRegCount, &decInsn,
5319 kRegTypeFloat, kRegTypeFloat, kRegTypeFloat, false, &failure);
5321 case OP_ADD_DOUBLE_2ADDR:
5322 case OP_SUB_DOUBLE_2ADDR:
5323 case OP_MUL_DOUBLE_2ADDR:
5324 case OP_DIV_DOUBLE_2ADDR:
5325 case OP_REM_DOUBLE_2ADDR:
5326 checkBinop2addr(workRegs, insnRegCount, &decInsn,
5327 kRegTypeDoubleLo, kRegTypeDoubleLo, kRegTypeDoubleLo, false,
5330 case OP_ADD_INT_LIT16:
5332 case OP_MUL_INT_LIT16:
5333 case OP_DIV_INT_LIT16:
5334 case OP_REM_INT_LIT16:
5335 checkLitop(workRegs, insnRegCount, &decInsn,
5336 kRegTypeInteger, kRegTypeInteger, false, &failure);
5338 case OP_AND_INT_LIT16:
5339 case OP_OR_INT_LIT16:
5340 case OP_XOR_INT_LIT16:
5341 checkLitop(workRegs, insnRegCount, &decInsn,
5342 kRegTypeInteger, kRegTypeInteger, true, &failure);
5344 case OP_ADD_INT_LIT8:
5345 case OP_RSUB_INT_LIT8:
5346 case OP_MUL_INT_LIT8:
5347 case OP_DIV_INT_LIT8:
5348 case OP_REM_INT_LIT8:
5349 case OP_SHL_INT_LIT8:
5350 checkLitop(workRegs, insnRegCount, &decInsn,
5351 kRegTypeInteger, kRegTypeInteger, false, &failure);
5353 case OP_SHR_INT_LIT8:
5354 tmpType = adjustForRightShift(workRegs, insnRegCount,
5355 decInsn.vB, decInsn.vC, false, &failure);
5356 checkLitop(workRegs, insnRegCount, &decInsn,
5357 tmpType, kRegTypeInteger, false, &failure);
5359 case OP_USHR_INT_LIT8:
5360 tmpType = adjustForRightShift(workRegs, insnRegCount,
5361 decInsn.vB, decInsn.vC, true, &failure);
5362 checkLitop(workRegs, insnRegCount, &decInsn,
5363 tmpType, kRegTypeInteger, false, &failure);
5365 case OP_AND_INT_LIT8:
5366 case OP_OR_INT_LIT8:
5367 case OP_XOR_INT_LIT8:
5368 checkLitop(workRegs, insnRegCount, &decInsn,
5369 kRegTypeInteger, kRegTypeInteger, true, &failure);
5373 * This falls into the general category of "optimized" instructions,
5374 * which don't generally appear during verification. Because it's
5375 * inserted in the course of verification, we can expect to see it here.
5377 case OP_THROW_VERIFICATION_ERROR:
5381 * Verifying "quickened" instructions is tricky, because we have
5382 * discarded the original field/method information. The byte offsets
5383 * and vtable indices only have meaning in the context of an object
5386 * If a piece of code declares a local reference variable, assigns
5387 * null to it, and then issues a virtual method call on it, we
5388 * cannot evaluate the method call during verification. This situation
5389 * isn't hard to handle, since we know the call will always result in an
5390 * NPE, and the arguments and return value don't matter. Any code that
5391 * depends on the result of the method call is inaccessible, so the
5392 * fact that we can't fully verify anything that comes after the bad
5393 * call is not a problem.
5395 * We must also consider the case of multiple code paths, only some of
5396 * which involve a null reference. We can completely verify the method
5397 * if we sidestep the results of executing with a null reference.
5398 * For example, if on the first pass through the code we try to do a
5399 * virtual method invocation through a null ref, we have to skip the
5400 * method checks and have the method return a "wildcard" type (which
5401 * merges with anything to become that other thing). The move-result
5402 * will tell us if it's a reference, single-word numeric, or double-word
5403 * value. We continue to perform the verification, and at the end of
5404 * the function any invocations that were never fully exercised are
5405 * marked as null-only.
5407 * We would do something similar for the field accesses. The field's
5408 * type, once known, can be used to recover the width of short integers.
5409 * If the object reference was null, the field-get returns the "wildcard"
5410 * type, which is acceptable for any operation.
5412 case OP_EXECUTE_INLINE:
5413 case OP_EXECUTE_INLINE_RANGE:
5414 case OP_INVOKE_DIRECT_EMPTY:
5416 case OP_IGET_WIDE_QUICK:
5417 case OP_IGET_OBJECT_QUICK:
5419 case OP_IPUT_WIDE_QUICK:
5420 case OP_IPUT_OBJECT_QUICK:
5421 case OP_INVOKE_VIRTUAL_QUICK:
5422 case OP_INVOKE_VIRTUAL_QUICK_RANGE:
5423 case OP_INVOKE_SUPER_QUICK:
5424 case OP_INVOKE_SUPER_QUICK_RANGE:
5425 failure = VERIFY_ERROR_GENERIC;
5428 /* these should never appear during verification */
5441 failure = VERIFY_ERROR_GENERIC;
5445 * DO NOT add a "default" clause here. Without it the compiler will
5446 * complain if an instruction is missing (which is desirable).
5450 if (!VERIFY_OK(failure)) {
5451 if (failure == VERIFY_ERROR_GENERIC || gDvm.optimizing) {
5452 /* immediate failure, reject class */
5453 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x\n",
5454 decInsn.opCode, insnIdx);
5457 /* replace opcode and continue on */
5458 LOGD("VFY: replacing opcode 0x%02x at 0x%04x\n",
5459 decInsn.opCode, insnIdx);
5460 if (!replaceFailingInstruction(meth, insnFlags, insnIdx, failure)) {
5461 LOG_VFY_METH(meth, "VFY: rejecting opcode 0x%02x at 0x%04x\n",
5462 decInsn.opCode, insnIdx);
5465 /* IMPORTANT: meth->insns may have been changed */
5466 insns = meth->insns + insnIdx;
5468 /* continue on as if we just handled a throw-verification-error */
5469 failure = VERIFY_ERROR_NONE;
5470 nextFlags = kInstrCanThrow;
5475 * If we didn't just set the result register, clear it out. This
5476 * ensures that you can only use "move-result" immediately after the
5477 * result is set. (We could check this statically, but it's not
5478 * expensive and it makes our debugging output cleaner.)
5480 if (!justSetResult) {
5481 int reg = RESULT_REGISTER(insnRegCount);
5482 workRegs[reg] = workRegs[reg+1] = kRegTypeUnknown;
5486 * Handle "continue". Tag the next consecutive instruction.
5488 if ((nextFlags & kInstrCanContinue) != 0) {
5489 int insnWidth = dvmInsnGetWidth(insnFlags, insnIdx);
5490 if (insnIdx+insnWidth >= insnsSize) {
5492 "VFY: execution can walk off end of code area (from 0x%x)\n",
5498 * The only way to get to a move-exception instruction is to get
5499 * thrown there. Make sure the next instruction isn't one.
5501 if (!checkMoveException(meth, insnIdx+insnWidth, "next"))
5504 if (getRegisterLine(regTable, insnIdx+insnWidth) != NULL) {
5506 * Merge registers into what we have for the next instruction,
5507 * and set the "changed" flag if needed.
5509 updateRegisters(meth, insnFlags, regTable, insnIdx+insnWidth,
5513 * We're not recording register data for the next instruction,
5514 * so we don't know what the prior state was. We have to
5515 * assume that something has changed and re-evaluate it.
5517 dvmInsnSetChanged(insnFlags, insnIdx+insnWidth, true);
5522 * Handle "branch". Tag the branch target.
5524 * NOTE: instructions like OP_EQZ provide information about the state
5525 * of the register when the branch is taken or not taken. For example,
5526 * somebody could get a reference field, check it for zero, and if the
5527 * branch is taken immediately store that register in a boolean field
5528 * since the value is known to be zero. We do not currently account for
5529 * that, and will reject the code.
5531 if ((nextFlags & kInstrCanBranch) != 0) {
5534 if (!dvmGetBranchTarget(meth, insnFlags, insnIdx, &branchTarget,
5537 /* should never happen after static verification */
5538 LOG_VFY_METH(meth, "VFY: bad branch at %d\n", insnIdx);
5541 assert(isConditional || (nextFlags & kInstrCanContinue) == 0);
5542 assert(!isConditional || (nextFlags & kInstrCanContinue) != 0);
5544 if (!checkMoveException(meth, insnIdx+branchTarget, "branch"))
5547 /* update branch target, set "changed" if appropriate */
5548 updateRegisters(meth, insnFlags, regTable, insnIdx+branchTarget,
5553 * Handle "switch". Tag all possible branch targets.
5555 * We've already verified that the table is structurally sound, so we
5556 * just need to walk through and tag the targets.
5558 if ((nextFlags & kInstrCanSwitch) != 0) {
5559 int offsetToSwitch = insns[1] | (((s4)insns[2]) << 16);
5560 const u2* switchInsns = insns + offsetToSwitch;
5561 int switchCount = switchInsns[1];
5562 int offsetToTargets, targ;
5564 if ((*insns & 0xff) == OP_PACKED_SWITCH) {
5565 /* 0=sig, 1=count, 2/3=firstKey */
5566 offsetToTargets = 4;
5568 /* 0=sig, 1=count, 2..count*2 = keys */
5569 assert((*insns & 0xff) == OP_SPARSE_SWITCH);
5570 offsetToTargets = 2 + 2*switchCount;
5573 /* verify each switch target */
5574 for (targ = 0; targ < switchCount; targ++) {
5575 int offset, absOffset;
5577 /* offsets are 32-bit, and only partly endian-swapped */
5578 offset = switchInsns[offsetToTargets + targ*2] |
5579 (((s4) switchInsns[offsetToTargets + targ*2 +1]) << 16);
5580 absOffset = insnIdx + offset;
5582 assert(absOffset >= 0 && absOffset < insnsSize);
5584 if (!checkMoveException(meth, absOffset, "switch"))
5587 updateRegisters(meth, insnFlags, regTable, absOffset, workRegs);
5592 * Handle instructions that can throw and that are sitting in a
5593 * "try" block. (If they're not in a "try" block when they throw,
5594 * control transfers out of the method.)
5596 if ((nextFlags & kInstrCanThrow) != 0 && dvmInsnIsInTry(insnFlags, insnIdx))
5598 const DexCode* pCode = dvmGetMethodCode(meth);
5599 DexCatchIterator iterator;
5601 if (dexFindCatchHandler(&iterator, pCode, insnIdx)) {
5603 DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
5605 if (handler == NULL) {
5609 /* note we use entryRegs, not workRegs */
5610 updateRegisters(meth, insnFlags, regTable, handler->address,
5617 * Update startGuess. Advance to the next instruction of that's
5618 * possible, otherwise use the branch target if one was found. If
5619 * neither of those exists we're in a return or throw; leave startGuess
5620 * alone and let the caller sort it out.
5622 if ((nextFlags & kInstrCanContinue) != 0) {
5623 *pStartGuess = insnIdx + dvmInsnGetWidth(insnFlags, insnIdx);
5624 } else if ((nextFlags & kInstrCanBranch) != 0) {
5625 /* we're still okay if branchTarget is zero */
5626 *pStartGuess = insnIdx + branchTarget;
5629 assert(*pStartGuess >= 0 && *pStartGuess < insnsSize &&
5630 dvmInsnGetWidth(insnFlags, *pStartGuess) != 0);
5640 * callback function used in dumpRegTypes to print local vars
5641 * valid at a given address.
5643 static void logLocalsCb(void *cnxt, u2 reg, u4 startAddress, u4 endAddress,
5644 const char *name, const char *descriptor,
5645 const char *signature)
5647 int addr = *((int *)cnxt);
5649 if (addr >= (int) startAddress && addr < (int) endAddress)
5651 LOGI(" %2d: '%s' %s\n", reg, name, descriptor);
5656 * Dump the register types for the specifed address to the log file.
5658 static void dumpRegTypes(const Method* meth, const InsnFlags* insnFlags,
5659 const RegType* addrRegs, int addr, const char* addrName,
5660 const UninitInstanceMap* uninitMap, int displayFlags)
5662 int regCount = meth->registersSize;
5663 int fullRegCount = regCount + kExtraRegs;
5664 bool branchTarget = dvmInsnIsBranchTarget(insnFlags, addr);
5667 assert(addr >= 0 && addr < (int) dvmGetMethodInsnsSize(meth));
5669 int regCharSize = fullRegCount + (fullRegCount-1)/4 + 2 +1;
5670 char regChars[regCharSize +1];
5671 memset(regChars, ' ', regCharSize);
5676 regChars[1 + (regCount-1) + (regCount-1)/4 +1] = ']';
5677 regChars[regCharSize] = '\0';
5679 //const RegType* addrRegs = getRegisterLine(regTable, addr);
5681 for (i = 0; i < regCount + kExtraRegs; i++) {
5684 switch (addrRegs[i]) {
5685 case kRegTypeUnknown: tch = '.'; break;
5686 case kRegTypeConflict: tch = 'X'; break;
5687 case kRegTypeFloat: tch = 'F'; break;
5688 case kRegTypeZero: tch = '0'; break;
5689 case kRegTypeOne: tch = '1'; break;
5690 case kRegTypeBoolean: tch = 'Z'; break;
5691 case kRegTypePosByte: tch = 'b'; break;
5692 case kRegTypeByte: tch = 'B'; break;
5693 case kRegTypePosShort: tch = 's'; break;
5694 case kRegTypeShort: tch = 'S'; break;
5695 case kRegTypeChar: tch = 'C'; break;
5696 case kRegTypeInteger: tch = 'I'; break;
5697 case kRegTypeLongLo: tch = 'J'; break;
5698 case kRegTypeLongHi: tch = 'j'; break;
5699 case kRegTypeDoubleLo: tch = 'D'; break;
5700 case kRegTypeDoubleHi: tch = 'd'; break;
5702 if (regTypeIsReference(addrRegs[i])) {
5703 if (regTypeIsUninitReference(addrRegs[i]))
5715 regChars[1 + i + (i/4)] = tch;
5717 regChars[1 + i + (i/4) + 2] = tch;
5720 if (addr == 0 && addrName != NULL)
5721 LOGI("%c%s %s\n", branchTarget ? '>' : ' ', addrName, regChars);
5723 LOGI("%c0x%04x %s\n", branchTarget ? '>' : ' ', addr, regChars);
5725 if (displayFlags & DRT_SHOW_REF_TYPES) {
5726 for (i = 0; i < regCount + kExtraRegs; i++) {
5727 if (regTypeIsReference(addrRegs[i]) && addrRegs[i] != kRegTypeZero)
5731 clazz = regTypeReferenceToClass(addrRegs[i], uninitMap);
5732 assert(dvmValidateObject((Object*)clazz));
5734 LOGI(" %2d: 0x%08x %s%s\n",
5736 regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "",
5739 LOGI(" RS: 0x%08x %s%s\n",
5741 regTypeIsUninitReference(addrRegs[i]) ? "[U]" : "",
5747 if (displayFlags & DRT_SHOW_LOCALS) {
5748 dexDecodeDebugInfo(meth->clazz->pDvmDex->pDexFile,
5749 dvmGetMethodCode(meth),
5750 meth->clazz->descriptor,
5751 meth->prototype.protoIdx,
5753 NULL, logLocalsCb, &addr);