DvmDex.cpp revision fb119e6cf8b47d53f024cae889487a17eacbf19f
1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * VM-specific state associated with a DEX file. 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create auxillary data structures. 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * We need a 4-byte pointer for every reference to a class, method, field, 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * or string constant. Summed up over all loaded DEX files (including the 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * whoppers in the boostrap class path), this adds up to be quite a bit 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * of native memory. 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * For more traditional VMs these values could be stuffed into the loaded 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class file constant pool area, but we don't have that luxury since our 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * classes are memory-mapped read-only. 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The DEX optimizer will remove the need for some of these (e.g. we won't 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * use the entry for virtual methods that are only called through 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * invoke-virtual-quick), creating the possibility of some space reduction 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * at dexopt time. 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic DvmDex* allocateAuxStructures(DexFile* pDexFile) 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DvmDex* pDvmDex; 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexHeader* pHeader; 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 stringCount, classCount, methodCount, fieldCount; 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex = (DvmDex*) calloc(1, sizeof(DvmDex)); 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pDexFile = pDexFile; 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pHeader = pDexFile->pHeader; 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pHeader = pDvmDex->pHeader; 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stringCount = pHeader->stringIdsSize; 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project classCount = pHeader->typeIdsSize; 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodCount = pHeader->methodIdsSize; 58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fieldCount = pHeader->fieldIdsSize; 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if (DVM_RESOLVER_CACHE == DVM_RC_REDUCING) || \ 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (DVM_RESOLVER_CACHE == DVM_RC_EXPANDING) 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile->indexMap.stringReducedCount > 0) 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stringCount = pDexFile->indexMap.stringReducedCount; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile->indexMap.classReducedCount > 0) 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project classCount = pDexFile->indexMap.classReducedCount; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile->indexMap.methodReducedCount > 0) 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project methodCount = pDexFile->indexMap.methodReducedCount; 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile->indexMap.fieldReducedCount > 0) 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fieldCount = pDexFile->indexMap.fieldReducedCount; 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#elif (DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE) 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project stringCount = classCount = methodCount = fieldCount = 0; 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResStrings = (struct StringObject**) 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project calloc(stringCount, sizeof(struct StringObject*)); 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResClasses = (struct ClassObject**) 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project calloc(classCount, sizeof(struct ClassObject*)); 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResMethods = (struct Method**) 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project calloc(methodCount, sizeof(struct Method*)); 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResFields = (struct Field**) 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project calloc(fieldCount, sizeof(struct Field*)); 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("+++ DEX %p: allocateAux %d+%d+%d+%d * 4 = %d bytes\n", 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex, stringCount, classCount, methodCount, fieldCount, 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (stringCount + classCount + methodCount + fieldCount) * 4); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pInterfaceCache = dvmAllocAtomicCache(DEX_INTERFACE_CACHE_SIZE); 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex->pResStrings == NULL || 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResClasses == NULL || 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResMethods == NULL || 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResFields == NULL || 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pInterfaceCache == NULL) 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Alloc failure in allocateAuxStructures\n"); 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResStrings); 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResClasses); 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResMethods); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResFields); 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex); 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pDvmDex; 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given an open optimized DEX file, map it into read-only shared memory and 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * parse the contents. 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns nonzero on error. 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex) 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DvmDex* pDvmDex; 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexFile* pDexFile; 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MemMapping memMap; 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int parseFlags = kDexParseDefault; 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = -1; 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.verifyDexChecksum) 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseFlags |= kDexParseVerifyChecksum; 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (lseek(fd, 0, SEEK_SET) < 0) { 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("lseek rewind failed\n"); 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 133b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysMapFileInShmemWritableReadOnly(fd, &memMap) != 0) { 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Unable to map file\n"); 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDexFile = dexFileParse(memMap.addr, memMap.length, parseFlags); 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile == NULL) { 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("DEX parse failed\n"); 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysReleaseShmem(&memMap); 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex = allocateAuxStructures(pDexFile); 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) { 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexFileFree(pDexFile); 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysReleaseShmem(&memMap); 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* tuck this into the DexFile so it gets released later */ 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysCopyMap(&pDvmDex->memMap, &memMap); 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ppDvmDex = pDvmDex; 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = 0; 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a DexFile structure for a "partial" DEX. This is one that is in 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the process of being optimized. The optimization header isn't finished 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and we won't have any of the auxillary data tables, so we have to do 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the initialization slightly differently. 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns nonzero on error. 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex) 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DvmDex* pDvmDex; 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexFile* pDexFile; 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int parseFlags = kDexParseDefault; 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = -1; 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 176e1f560a62949e9a673a58a37a8c72dc8b15d9563Andy McFadden /* -- file is incomplete, new checksum has not yet been calculated 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.verifyDexChecksum) 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseFlags |= kDexParseVerifyChecksum; 179e1f560a62949e9a673a58a37a8c72dc8b15d9563Andy McFadden */ 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDexFile = dexFileParse(addr, len, parseFlags); 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile == NULL) { 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("DEX parse failed\n"); 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex = allocateAuxStructures(pDexFile); 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) { 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexFileFree(pDexFile); 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ppDvmDex = pDvmDex; 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = 0; 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free up the DexFile and any associated data structures. 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note we may be called with a partially-initialized DvmDex. 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDexFileFree(DvmDex* pDvmDex) 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexFileFree(pDvmDex->pDexFile); 210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("+++ DEX %p: freeing aux structs\n", pDvmDex); 212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResStrings); 213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResClasses); 214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResMethods); 215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResFields); 216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFreeAtomicCache(pDvmDex->pInterfaceCache); 217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysReleaseShmem(&pDvmDex->memMap); 219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex); 220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 22296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 22396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 22496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Change the byte at the specified address to a new value. If the location 22596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * already has the new value, do nothing. 22696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 22796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * This requires changing the access permissions to read-write, updating 22896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * the value, and then resetting the permissions. 22996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 230fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We need to ensure mutual exclusion at a page granularity to avoid a race 231fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * where one threads sets read-write, another thread sets read-only, and 232fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * then the first thread does a write. Since we don't do a lot of updates, 233fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * and the window is small, we just use a lock across the entire DvmDex. 234fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We're only trying to make the page state change atomic; it's up to the 235fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * caller to ensure that multiple threads aren't stomping on the same 236fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * location (e.g. breakpoints and verifier/optimizer changes happening 237fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * simultaneously). 23896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 23996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * TODO: if we're back to the original state of the page, use 24096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * madvise(MADV_DONTNEED) to release the private/dirty copy. 24196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 24296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" on success. 24396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 24496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenbool dvmDexChangeDex1(DvmDex* pDvmDex, u1* addr, u1 newVal) 24596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 24696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (*addr == newVal) { 24796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden LOGV("+++ byte at %p is already 0x%02x\n", addr, newVal); 24896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 24996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 25096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 251fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden /* 252fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We're not holding this for long, so we don't bother with switching 253fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * to VMWAIT. 254fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden */ 255fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmLockMutex(&pDvmDex->modLock); 256fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 25796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden LOGV("+++ change byte at %p from 0x%02x to 0x%02x\n", addr, *addr, newVal); 258b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 1, true, &pDvmDex->memMap) != 0) { 259b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden LOGD("NOTE: DEX page access change (->RW) failed\n"); 260b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going (may crash) */ 26196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 26296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 26396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *addr = newVal; 26496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 265b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 1, false, &pDvmDex->memMap) != 0) { 266b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden LOGD("NOTE: DEX page access change (->RO) failed\n"); 267b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going */ 26896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 26996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 270fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmUnlockMutex(&pDvmDex->modLock); 271fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 27296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 27396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 27496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 27596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 27696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Change the 2-byte value at the specified address to a new value. If the 27796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * location already has the new value, do nothing. 27896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 27996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Otherwise works like dvmDexChangeDex1. 28096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 28196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenbool dvmDexChangeDex2(DvmDex* pDvmDex, u2* addr, u2 newVal) 28296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 28396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (*addr == newVal) { 28496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden LOGV("+++ value at %p is already 0x%04x\n", addr, newVal); 28596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 28696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 28796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 288fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden /* 289fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We're not holding this for long, so we don't bother with switching 290fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * to VMWAIT. 291fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden */ 292fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmLockMutex(&pDvmDex->modLock); 293fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 29496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden LOGV("+++ change 2byte at %p from 0x%04x to 0x%04x\n", addr, *addr, newVal); 295b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 2, true, &pDvmDex->memMap) != 0) { 296b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden LOGD("NOTE: DEX page access change (->RW) failed\n"); 297b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going (may crash) */ 29896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 29996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 30096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *addr = newVal; 30196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 302b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 2, false, &pDvmDex->memMap) != 0) { 303b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden LOGD("NOTE: DEX page access change (->RO) failed\n"); 304b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going */ 30596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 30696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 307fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmUnlockMutex(&pDvmDex->modLock); 308fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 30996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 31096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 311