DvmDex.cpp revision c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2ef
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 pDvmDex->pResStrings = (struct StringObject**) 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project calloc(stringCount, sizeof(struct StringObject*)); 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResClasses = (struct ClassObject**) 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project calloc(classCount, sizeof(struct ClassObject*)); 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResMethods = (struct Method**) 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project calloc(methodCount, sizeof(struct Method*)); 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResFields = (struct Field**) 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project calloc(fieldCount, sizeof(struct Field*)); 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 7292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ DEX %p: allocateAux %d+%d+%d+%d * 4 = %d bytes", 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex, stringCount, classCount, methodCount, fieldCount, 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (stringCount + classCount + methodCount + fieldCount) * 4); 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pInterfaceCache = dvmAllocAtomicCache(DEX_INTERFACE_CACHE_SIZE); 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex->pResStrings == NULL || 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResClasses == NULL || 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResMethods == NULL || 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pResFields == NULL || 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pInterfaceCache == NULL) 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 84c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Alloc failure in allocateAuxStructures"); 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResStrings); 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResClasses); 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResMethods); 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResFields); 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex); 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return NULL; 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pDvmDex; 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given an open optimized DEX file, map it into read-only shared memory and 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * parse the contents. 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns nonzero on error. 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex) 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DvmDex* pDvmDex; 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexFile* pDexFile; 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MemMapping memMap; 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int parseFlags = kDexParseDefault; 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = -1; 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.verifyDexChecksum) 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseFlags |= kDexParseVerifyChecksum; 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (lseek(fd, 0, SEEK_SET) < 0) { 115c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("lseek rewind failed"); 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 119b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysMapFileInShmemWritableReadOnly(fd, &memMap) != 0) { 120c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unable to map file"); 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 124fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro pDexFile = dexFileParse((u1*)memMap.addr, memMap.length, parseFlags); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile == NULL) { 126c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DEX parse failed"); 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysReleaseShmem(&memMap); 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex = allocateAuxStructures(pDexFile); 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) { 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexFileFree(pDexFile); 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysReleaseShmem(&memMap); 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* tuck this into the DexFile so it gets released later */ 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysCopyMap(&pDvmDex->memMap, &memMap); 14057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden pDvmDex->isMappedReadOnly = true; 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ppDvmDex = pDvmDex; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = 0; 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a DexFile structure for a "partial" DEX. This is one that is in 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the process of being optimized. The optimization header isn't finished 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and we won't have any of the auxillary data tables, so we have to do 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the initialization slightly differently. 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns nonzero on error. 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex) 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DvmDex* pDvmDex; 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexFile* pDexFile; 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int parseFlags = kDexParseDefault; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = -1; 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 163e1f560a62949e9a673a58a37a8c72dc8b15d9563Andy McFadden /* -- file is incomplete, new checksum has not yet been calculated 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.verifyDexChecksum) 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseFlags |= kDexParseVerifyChecksum; 166e1f560a62949e9a673a58a37a8c72dc8b15d9563Andy McFadden */ 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 168fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro pDexFile = dexFileParse((u1*)addr, len, parseFlags); 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile == NULL) { 170c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DEX parse failed"); 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex = allocateAuxStructures(pDexFile); 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) { 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexFileFree(pDexFile); 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden pDvmDex->isMappedReadOnly = false; 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ppDvmDex = pDvmDex; 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = 0; 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free up the DexFile and any associated data structures. 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note we may be called with a partially-initialized DvmDex. 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDexFileFree(DvmDex* pDvmDex) 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexFileFree(pDvmDex->pDexFile); 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ DEX %p: freeing aux structs", pDvmDex); 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResStrings); 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResClasses); 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResMethods); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex->pResFields); 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmFreeAtomicCache(pDvmDex->pInterfaceCache); 205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysReleaseShmem(&pDvmDex->memMap); 207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(pDvmDex); 208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 21096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 21196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 21296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Change the byte at the specified address to a new value. If the location 21396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * already has the new value, do nothing. 21496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 21596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * This requires changing the access permissions to read-write, updating 21696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * the value, and then resetting the permissions. 21796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 218fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We need to ensure mutual exclusion at a page granularity to avoid a race 219fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * where one threads sets read-write, another thread sets read-only, and 220fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * then the first thread does a write. Since we don't do a lot of updates, 221fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * and the window is small, we just use a lock across the entire DvmDex. 222fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We're only trying to make the page state change atomic; it's up to the 223fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * caller to ensure that multiple threads aren't stomping on the same 224fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * location (e.g. breakpoints and verifier/optimizer changes happening 225fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * simultaneously). 22696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 22796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * TODO: if we're back to the original state of the page, use 22896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * madvise(MADV_DONTNEED) to release the private/dirty copy. 22996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 23096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" on success. 23196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 23296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenbool dvmDexChangeDex1(DvmDex* pDvmDex, u1* addr, u1 newVal) 23396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 23496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (*addr == newVal) { 23592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ byte at %p is already 0x%02x", addr, newVal); 23696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 23796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 23896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 239fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden /* 240fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We're not holding this for long, so we don't bother with switching 241fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * to VMWAIT. 242fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden */ 243fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmLockMutex(&pDvmDex->modLock); 244fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 24592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ change byte at %p from 0x%02x to 0x%02x", addr, *addr, newVal); 246b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 1, true, &pDvmDex->memMap) != 0) { 247062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("NOTE: DEX page access change (->RW) failed"); 248b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going (may crash) */ 24996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 25096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 25196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *addr = newVal; 25296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 253b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 1, false, &pDvmDex->memMap) != 0) { 254062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("NOTE: DEX page access change (->RO) failed"); 255b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going */ 25696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 25796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 258fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmUnlockMutex(&pDvmDex->modLock); 259fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 26096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 26196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 26296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 26396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 26496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Change the 2-byte value at the specified address to a new value. If the 26596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * location already has the new value, do nothing. 26696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 26796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Otherwise works like dvmDexChangeDex1. 26896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 26996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenbool dvmDexChangeDex2(DvmDex* pDvmDex, u2* addr, u2 newVal) 27096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 27196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (*addr == newVal) { 27292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ value at %p is already 0x%04x", addr, newVal); 27396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 27496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 27596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 276fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden /* 277fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We're not holding this for long, so we don't bother with switching 278fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * to VMWAIT. 279fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden */ 280fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmLockMutex(&pDvmDex->modLock); 281fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 28292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ change 2byte at %p from 0x%04x to 0x%04x", addr, *addr, newVal); 283b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 2, true, &pDvmDex->memMap) != 0) { 284062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("NOTE: DEX page access change (->RW) failed"); 285b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going (may crash) */ 28696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 28796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 28896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *addr = newVal; 28996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 290b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 2, false, &pDvmDex->memMap) != 0) { 291062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("NOTE: DEX page access change (->RO) failed"); 292b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going */ 29396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 29496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 295fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmUnlockMutex(&pDvmDex->modLock); 296fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 29796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 29896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 299