1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * Dalvik bytecode verifier. 19 */ 20 #ifndef _DALVIK_CODEVERIFY 21 #define _DALVIK_CODEVERIFY 22 23 #include "analysis/VerifySubs.h" 24 25 26 /* 27 * Enumeration for register type values. The "hi" piece of a 64-bit value 28 * MUST immediately follow the "lo" piece in the enumeration, so we can check 29 * that hi==lo+1. 30 * 31 * Assignment of constants: 32 * [-MAXINT,-32768) : integer 33 * [-32768,-128) : short 34 * [-128,0) : byte 35 * 0 : zero 36 * 1 : one 37 * [2,128) : posbyte 38 * [128,32768) : posshort 39 * [32768,65536) : char 40 * [65536,MAXINT] : integer 41 * 42 * Allowed "implicit" widening conversions: 43 * zero -> boolean, posbyte, byte, posshort, short, char, integer, ref (null) 44 * one -> boolean, posbyte, byte, posshort, short, char, integer 45 * boolean -> posbyte, byte, posshort, short, char, integer 46 * posbyte -> posshort, short, integer, char 47 * byte -> short, integer 48 * posshort -> integer, char 49 * short -> integer 50 * char -> integer 51 * 52 * In addition, all of the above can convert to "float". 53 * 54 * We're more careful with integer values than the spec requires. The 55 * motivation is to restrict byte/char/short to the correct range of values. 56 * For example, if a method takes a byte argument, we don't want to allow 57 * the code to load the constant "1024" and pass it in. 58 */ 59 enum { 60 kRegTypeUnknown = 0, /* initial state; use value=0 so calloc works */ 61 kRegTypeUninit = 1, /* MUST be odd to distinguish from pointer */ 62 kRegTypeConflict, /* merge clash makes this reg's type unknowable */ 63 64 /* 65 * Category-1nr types. The order of these is chiseled into a couple 66 * of tables, so don't add, remove, or reorder if you can avoid it. 67 */ 68 #define kRegType1nrSTART kRegTypeFloat 69 kRegTypeFloat, 70 kRegTypeZero, /* 32-bit 0, could be Boolean, Int, Float, or Ref */ 71 kRegTypeOne, /* 32-bit 1, could be Boolean, Int, Float */ 72 kRegTypeBoolean, /* must be 0 or 1 */ 73 kRegTypePosByte, /* byte, known positive (can become char) */ 74 kRegTypeByte, 75 kRegTypePosShort, /* short, known positive (can become char) */ 76 kRegTypeShort, 77 kRegTypeChar, 78 kRegTypeInteger, 79 #define kRegType1nrEND kRegTypeInteger 80 81 kRegTypeLongLo, /* lower-numbered register; endian-independent */ 82 kRegTypeLongHi, 83 kRegTypeDoubleLo, 84 kRegTypeDoubleHi, 85 86 /* 87 * Enumeration max; this is used with "full" (32-bit) RegType values. 88 * 89 * Anything larger than this is a ClassObject or uninit ref. Mask off 90 * all but the low 8 bits; if you're left with kRegTypeUninit, pull 91 * the uninit index out of the high 24. Because kRegTypeUninit has an 92 * odd value, there is no risk of a particular ClassObject pointer bit 93 * pattern being confused for it (assuming our class object allocator 94 * uses word alignment). 95 */ 96 kRegTypeMAX 97 }; 98 #define kRegTypeUninitMask 0xff 99 #define kRegTypeUninitShift 8 100 101 /* 102 * RegType holds information about the type of data held in a register. 103 * For most types it's a simple enum. For reference types it holds a 104 * pointer to the ClassObject, and for uninitialized references it holds 105 * an index into the UninitInstanceMap. 106 */ 107 typedef u4 RegType; 108 109 /* table with merge logic for primitive types */ 110 extern const char gDvmMergeTab[kRegTypeMAX][kRegTypeMAX]; 111 112 113 /* 114 * Returns "true" if the flags indicate that this address holds the start 115 * of an instruction. 116 */ 117 INLINE bool dvmInsnIsOpcode(const InsnFlags* insnFlags, int addr) { 118 return (insnFlags[addr] & kInsnFlagWidthMask) != 0; 119 } 120 121 /* 122 * Extract the unsigned 16-bit instruction width from "flags". 123 */ 124 INLINE int dvmInsnGetWidth(const InsnFlags* insnFlags, int addr) { 125 return insnFlags[addr] & kInsnFlagWidthMask; 126 } 127 128 /* 129 * Changed? 130 */ 131 INLINE bool dvmInsnIsChanged(const InsnFlags* insnFlags, int addr) { 132 return (insnFlags[addr] & kInsnFlagChanged) != 0; 133 } 134 INLINE void dvmInsnSetChanged(InsnFlags* insnFlags, int addr, bool changed) 135 { 136 if (changed) 137 insnFlags[addr] |= kInsnFlagChanged; 138 else 139 insnFlags[addr] &= ~kInsnFlagChanged; 140 } 141 142 /* 143 * Visited? 144 */ 145 INLINE bool dvmInsnIsVisited(const InsnFlags* insnFlags, int addr) { 146 return (insnFlags[addr] & kInsnFlagVisited) != 0; 147 } 148 INLINE void dvmInsnSetVisited(InsnFlags* insnFlags, int addr, bool changed) 149 { 150 if (changed) 151 insnFlags[addr] |= kInsnFlagVisited; 152 else 153 insnFlags[addr] &= ~kInsnFlagVisited; 154 } 155 156 /* 157 * Visited or changed? 158 */ 159 INLINE bool dvmInsnIsVisitedOrChanged(const InsnFlags* insnFlags, int addr) { 160 return (insnFlags[addr] & (kInsnFlagVisited|kInsnFlagChanged)) != 0; 161 } 162 163 /* 164 * In a "try" block? 165 */ 166 INLINE bool dvmInsnIsInTry(const InsnFlags* insnFlags, int addr) { 167 return (insnFlags[addr] & kInsnFlagInTry) != 0; 168 } 169 INLINE void dvmInsnSetInTry(InsnFlags* insnFlags, int addr, bool inTry) 170 { 171 assert(inTry); 172 //if (inTry) 173 insnFlags[addr] |= kInsnFlagInTry; 174 //else 175 // insnFlags[addr] &= ~kInsnFlagInTry; 176 } 177 178 /* 179 * Instruction is a branch target or exception handler? 180 */ 181 INLINE bool dvmInsnIsBranchTarget(const InsnFlags* insnFlags, int addr) { 182 return (insnFlags[addr] & kInsnFlagBranchTarget) != 0; 183 } 184 INLINE void dvmInsnSetBranchTarget(InsnFlags* insnFlags, int addr, 185 bool isBranch) 186 { 187 assert(isBranch); 188 //if (isBranch) 189 insnFlags[addr] |= kInsnFlagBranchTarget; 190 //else 191 // insnFlags[addr] &= ~kInsnFlagBranchTarget; 192 } 193 194 /* 195 * Instruction is a GC point? 196 */ 197 INLINE bool dvmInsnIsGcPoint(const InsnFlags* insnFlags, int addr) { 198 return (insnFlags[addr] & kInsnFlagGcPoint) != 0; 199 } 200 INLINE void dvmInsnSetGcPoint(InsnFlags* insnFlags, int addr, 201 bool isGcPoint) 202 { 203 assert(isGcPoint); 204 //if (isGcPoint) 205 insnFlags[addr] |= kInsnFlagGcPoint; 206 //else 207 // insnFlags[addr] &= ~kInsnFlagGcPoint; 208 } 209 210 211 /* 212 * Table that maps uninitialized instances to classes, based on the 213 * address of the new-instance instruction. 214 */ 215 typedef struct UninitInstanceMap { 216 int numEntries; 217 struct { 218 int addr; /* code offset, or -1 for method arg ("this") */ 219 ClassObject* clazz; /* class created at this address */ 220 } map[1]; 221 } UninitInstanceMap; 222 #define kUninitThisArgAddr (-1) 223 #define kUninitThisArgSlot 0 224 225 /* 226 * Create a new UninitInstanceMap. 227 */ 228 UninitInstanceMap* dvmCreateUninitInstanceMap(const Method* meth, 229 const InsnFlags* insnFlags, int newInstanceCount); 230 231 /* 232 * Release the storage associated with an UninitInstanceMap. 233 */ 234 void dvmFreeUninitInstanceMap(UninitInstanceMap* uninitMap); 235 236 /* 237 * Associate a class with an address. Returns the map slot index, or -1 238 * if the address isn't listed in the map (shouldn't happen) or if a 239 * different class is already associated with the address (shouldn't 240 * happen either). 241 */ 242 //int dvmSetUninitInstance(UninitInstanceMap* uninitMap, int addr, 243 // ClassObject* clazz); 244 245 /* 246 * Return the class associated with an uninitialized reference. Pass in 247 * the map index. 248 */ 249 //ClassObject* dvmGetUninitInstance(const UninitInstanceMap* uninitMap, int idx); 250 251 /* 252 * Clear the class associated with an uninitialized reference. Pass in 253 * the map index. 254 */ 255 //void dvmClearUninitInstance(UninitInstanceMap* uninitMap, int idx); 256 257 258 /* 259 * Verify bytecode in "meth". "insnFlags" should be populated with 260 * instruction widths and "in try" flags. 261 */ 262 bool dvmVerifyCodeFlow(Method* meth, InsnFlags* insnFlags, 263 UninitInstanceMap* uninitMap); 264 265 #endif /*_DALVIK_CODEVERIFY*/ 266