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 * The VM wraps some additional data structures around the DexFile. These 19 * are defined here. 20 */ 21 #ifndef _DALVIK_DVMDEX 22 #define _DALVIK_DVMDEX 23 24 #include "libdex/DexFile.h" 25 26 /* extern */ 27 struct ClassObject; 28 struct HashTable; 29 struct InstField; 30 struct Method; 31 struct StringObject; 32 33 34 /* 35 * Some additional VM data structures that are associated with the DEX file. 36 */ 37 typedef struct DvmDex { 38 /* pointer to the DexFile we're associated with */ 39 DexFile* pDexFile; 40 41 /* clone of pDexFile->pHeader (it's used frequently enough) */ 42 const DexHeader* pHeader; 43 44 /* interned strings; parallel to "stringIds" */ 45 struct StringObject** pResStrings; 46 47 /* resolved classes; parallel to "typeIds" */ 48 struct ClassObject** pResClasses; 49 50 /* resolved methods; parallel to "methodIds" */ 51 struct Method** pResMethods; 52 53 /* resolved instance fields; parallel to "fieldIds" */ 54 /* (this holds both InstField and StaticField) */ 55 struct Field** pResFields; 56 57 /* interface method lookup cache */ 58 struct AtomicCache* pInterfaceCache; 59 60 /* shared memory region with file contents */ 61 MemMapping memMap; 62 } DvmDex; 63 64 65 /* 66 * Given a file descriptor for an open "optimized" DEX file, map it into 67 * memory and parse the contents. 68 * 69 * On success, returns 0 and sets "*ppDvmDex" to a newly-allocated DvmDex. 70 * On failure, returns a meaningful error code [currently just -1]. 71 */ 72 int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex); 73 74 /* 75 * Open a partial DEX file. Only useful as part of the optimization process. 76 */ 77 int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex); 78 79 /* 80 * Free a DvmDex structure, along with any associated structures. 81 */ 82 void dvmDexFileFree(DvmDex* pDvmDex); 83 84 85 /* 86 * Change the 1- or 2-byte value at the specified address to a new value. If 87 * the location already has the new value, do nothing. 88 * 89 * This does not make any synchronization guarantees. The caller must 90 * ensure exclusivity vs. other callers. 91 * 92 * For the 2-byte call, the pointer should have 16-bit alignment. 93 * 94 * Returns "true" on success. 95 */ 96 bool dvmDexChangeDex1(DvmDex* pDvmDex, u1* addr, u1 newVal); 97 bool dvmDexChangeDex2(DvmDex* pDvmDex, u2* addr, u2 newVal); 98 99 100 #if DVM_RESOLVER_CACHE == DVM_RC_DISABLED 101 /* 1:1 mapping */ 102 103 /* 104 * Return the requested item if it has been resolved, or NULL if it hasn't. 105 */ 106 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex, 107 u4 stringIdx) 108 { 109 assert(stringIdx < pDvmDex->pHeader->stringIdsSize); 110 return pDvmDex->pResStrings[stringIdx]; 111 } 112 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex, 113 u4 classIdx) 114 { 115 assert(classIdx < pDvmDex->pHeader->typeIdsSize); 116 return pDvmDex->pResClasses[classIdx]; 117 } 118 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex, 119 u4 methodIdx) 120 { 121 assert(methodIdx < pDvmDex->pHeader->methodIdsSize); 122 return pDvmDex->pResMethods[methodIdx]; 123 } 124 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex, 125 u4 fieldIdx) 126 { 127 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize); 128 return pDvmDex->pResFields[fieldIdx]; 129 } 130 131 /* 132 * Update the resolved item table. Resolution always produces the same 133 * result, so we're not worried about atomicity here. 134 */ 135 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx, 136 struct StringObject* str) 137 { 138 assert(stringIdx < pDvmDex->pHeader->stringIdsSize); 139 pDvmDex->pResStrings[stringIdx] = str; 140 } 141 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx, 142 struct ClassObject* clazz) 143 { 144 assert(classIdx < pDvmDex->pHeader->typeIdsSize); 145 pDvmDex->pResClasses[classIdx] = clazz; 146 } 147 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx, 148 struct Method* method) 149 { 150 assert(methodIdx < pDvmDex->pHeader->methodIdsSize); 151 pDvmDex->pResMethods[methodIdx] = method; 152 } 153 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx, 154 struct Field* field) 155 { 156 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize); 157 pDvmDex->pResFields[fieldIdx] = field; 158 } 159 160 #elif DVM_RESOLVER_CACHE == DVM_RC_REDUCING 161 /* reduce request to fit in a less-than-full-size cache table */ 162 163 /* 164 * Return the requested item if it has been resolved, or NULL if it hasn't. 165 * 166 * If we have a mapping table defined for this category, but there's no 167 * entry for this index, we always return NULL. Otherwise, we return the 168 * entry. (To regain some performance we may want to assume that the 169 * table exists when compiled in this mode -- avoids a null check but 170 * prevents us from switching back and forth without rebuilding the VM.) 171 * 172 * We could save an integer compare here by ensuring that map[kNoIndexMapping] 173 * always evalutes to NULL (e.g. set kNoIndexMapping = 0). 174 */ 175 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex, 176 u4 stringIdx) 177 { 178 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap; 179 180 assert(stringIdx < pDvmDex->pHeader->stringIdsSize); 181 if (pIndexMap->stringReducedCount > 0) { 182 stringIdx = pIndexMap->stringMap[stringIdx]; 183 if (stringIdx == kNoIndexMapping) 184 return NULL; 185 } 186 return pDvmDex->pResStrings[stringIdx]; 187 } 188 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex, 189 u4 classIdx) 190 { 191 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap; 192 193 assert(classIdx < pDvmDex->pHeader->typeIdsSize); 194 if (pIndexMap->classReducedCount > 0) { 195 classIdx = pIndexMap->classMap[classIdx]; 196 if (classIdx == kNoIndexMapping) 197 return NULL; 198 } 199 return pDvmDex->pResClasses[classIdx]; 200 } 201 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex, 202 u4 methodIdx) 203 { 204 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap; 205 206 assert(methodIdx < pDvmDex->pHeader->methodIdsSize); 207 if (pIndexMap->methodReducedCount > 0) { 208 methodIdx = pIndexMap->methodMap[methodIdx]; 209 if (methodIdx == kNoIndexMapping) 210 return NULL; 211 } 212 return pDvmDex->pResMethods[methodIdx]; 213 } 214 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex, 215 u4 fieldIdx) 216 { 217 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap; 218 219 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize); 220 if (pIndexMap->fieldReducedCount > 0) { 221 fieldIdx = pIndexMap->fieldMap[fieldIdx]; 222 if (fieldIdx == kNoIndexMapping) 223 return NULL; 224 } 225 return pDvmDex->pResFields[fieldIdx]; 226 } 227 228 /* 229 * Update the resolved item table. Resolution always produces the same 230 * result, so we're not worried about atomicity here. 231 */ 232 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx, 233 struct StringObject* str) 234 { 235 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap; 236 u4 newIdx; 237 238 assert(stringIdx < pDvmDex->pHeader->stringIdsSize); 239 if (pIndexMap->stringReducedCount > 0) { 240 newIdx = pIndexMap->stringMap[stringIdx]; 241 if (newIdx != kNoIndexMapping) 242 pDvmDex->pResStrings[newIdx] = str; 243 } 244 } 245 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx, 246 struct ClassObject* clazz) 247 { 248 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap; 249 u4 newIdx; 250 251 assert(classIdx < pDvmDex->pHeader->typeIdsSize); 252 if (pIndexMap->classReducedCount > 0) { 253 newIdx = pIndexMap->classMap[classIdx]; 254 if (newIdx != kNoIndexMapping) 255 pDvmDex->pResClasses[newIdx] = clazz; 256 } 257 } 258 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx, 259 struct Method* method) 260 { 261 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap; 262 u4 newIdx; 263 264 assert(methodIdx < pDvmDex->pHeader->methodIdsSize); 265 if (pIndexMap->methodReducedCount > 0) { 266 newIdx = pIndexMap->methodMap[methodIdx]; 267 if (newIdx != kNoIndexMapping) 268 pDvmDex->pResMethods[newIdx] = method; 269 } 270 } 271 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx, 272 struct Field* field) 273 { 274 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap; 275 u4 newIdx; 276 277 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize); 278 if (pIndexMap->fieldReducedCount > 0) { 279 newIdx = pIndexMap->fieldMap[fieldIdx]; 280 if (newIdx != kNoIndexMapping) 281 pDvmDex->pResFields[newIdx] = field; 282 } 283 } 284 285 #elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING 286 287 #error "not implemented" /* TODO */ 288 289 #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE 290 291 /* 292 * There's no cache, so we always return NULL. 293 */ 294 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex, 295 u4 stringIdx) 296 { 297 return NULL; 298 } 299 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex, 300 u4 classIdx) 301 { 302 return NULL; 303 } 304 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex, 305 u4 methodIdx) 306 { 307 return NULL; 308 } 309 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex, 310 u4 fieldIdx) 311 { 312 return NULL; 313 } 314 315 /* 316 * Update the resolved item table. There is no table, so do nothing. 317 */ 318 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx, 319 struct StringObject* str) 320 {} 321 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx, 322 struct ClassObject* clazz) 323 {} 324 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx, 325 struct Method* method) 326 {} 327 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx, 328 struct Field* field) 329 {} 330 331 #else 332 #error "huh?" 333 #endif /*DVM_RESOLVER_CACHE==N*/ 334 335 #endif /*_DALVIK_DVMDEX*/ 336