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" 215bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev#include <sys/mman.h> 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 */ 405bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic DvmDex* allocateAuxStructures(DexFile* pDexFile) 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DvmDex* pDvmDex; 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const DexHeader* pHeader; 455bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev u4 stringSize, classSize, methodSize, fieldSize; 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 475bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev pHeader = pDexFile->pHeader; 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 495bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev stringSize = pHeader->stringIdsSize * sizeof(struct StringObject*); 505bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev classSize = pHeader->typeIdsSize * sizeof(struct ClassObject*); 515bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev methodSize = pHeader->methodIdsSize * sizeof(struct Method*); 525bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev fieldSize = pHeader->fieldIdsSize * sizeof(struct Field*); 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 545bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev u4 totalSize = sizeof(DvmDex) + 555bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev stringSize + classSize + methodSize + fieldSize; 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 575bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev u1 *blob = (u1 *)dvmAllocRegion(totalSize, 585bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev PROT_READ | PROT_WRITE, "dalvik-aux-structure"); 595bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev if ((void *)blob == MAP_FAILED) 605bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev return NULL; 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 625bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev pDvmDex = (DvmDex*)blob; 635bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev blob += sizeof(DvmDex); 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 655bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev pDvmDex->pDexFile = pDexFile; 665bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev pDvmDex->pHeader = pHeader; 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 685bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev pDvmDex->pResStrings = (struct StringObject**)blob; 695bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev blob += stringSize; 705bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev pDvmDex->pResClasses = (struct ClassObject**)blob; 715bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev blob += classSize; 725bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev pDvmDex->pResMethods = (struct Method**)blob; 735bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev blob += methodSize; 745bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev pDvmDex->pResFields = (struct Field**)blob; 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 765bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev ALOGV("+++ DEX %p: allocateAux (%d+%d+%d+%d)*4 = %d bytes", 77bb046193c2da5d43a57b2fa8a17a0f634bf003baElliott Hughes pDvmDex, stringSize/4, classSize/4, methodSize/4, fieldSize/4, 785bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev stringSize + classSize + methodSize + fieldSize); 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex->pInterfaceCache = dvmAllocAtomicCache(DEX_INTERFACE_CACHE_SIZE); 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 82743639415bb123b1517e335bb97f202edbe4e599msg dvmInitMutex(&pDvmDex->modLock); 83743639415bb123b1517e335bb97f202edbe4e599msg 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return pDvmDex; 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Given an open optimized DEX file, map it into read-only shared memory and 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * parse the contents. 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns nonzero on error. 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex) 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DvmDex* pDvmDex; 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexFile* pDexFile; 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project MemMapping memMap; 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int parseFlags = kDexParseDefault; 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = -1; 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.verifyDexChecksum) 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseFlags |= kDexParseVerifyChecksum; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (lseek(fd, 0, SEEK_SET) < 0) { 105c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("lseek rewind failed"); 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 109b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysMapFileInShmemWritableReadOnly(fd, &memMap) != 0) { 110c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unable to map file"); 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 114fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro pDexFile = dexFileParse((u1*)memMap.addr, memMap.length, parseFlags); 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile == NULL) { 116c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DEX parse failed"); 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysReleaseShmem(&memMap); 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex = allocateAuxStructures(pDexFile); 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) { 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexFileFree(pDexFile); 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysReleaseShmem(&memMap); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* tuck this into the DexFile so it gets released later */ 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysCopyMap(&pDvmDex->memMap, &memMap); 13057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden pDvmDex->isMappedReadOnly = true; 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ppDvmDex = pDvmDex; 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = 0; 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Create a DexFile structure for a "partial" DEX. This is one that is in 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the process of being optimized. The optimization header isn't finished 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and we won't have any of the auxillary data tables, so we have to do 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the initialization slightly differently. 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns nonzero on error. 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex) 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DvmDex* pDvmDex; 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexFile* pDexFile; 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int parseFlags = kDexParseDefault; 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = -1; 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 153e1f560a62949e9a673a58a37a8c72dc8b15d9563Andy McFadden /* -- file is incomplete, new checksum has not yet been calculated 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (gDvm.verifyDexChecksum) 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project parseFlags |= kDexParseVerifyChecksum; 156e1f560a62949e9a673a58a37a8c72dc8b15d9563Andy McFadden */ 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 158fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro pDexFile = dexFileParse((u1*)addr, len, parseFlags); 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDexFile == NULL) { 160c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DEX parse failed"); 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project pDvmDex = allocateAuxStructures(pDexFile); 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) { 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexFileFree(pDexFile); 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 16957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden pDvmDex->isMappedReadOnly = false; 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *ppDvmDex = pDvmDex; 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = 0; 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Free up the DexFile and any associated data structures. 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Note we may be called with a partially-initialized DvmDex. 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectvoid dvmDexFileFree(DvmDex* pDvmDex) 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 1845bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev u4 totalSize; 1855bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pDvmDex == NULL) 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return; 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 189743639415bb123b1517e335bb97f202edbe4e599msg dvmDestroyMutex(&pDvmDex->modLock); 190743639415bb123b1517e335bb97f202edbe4e599msg 1915bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev totalSize = pDvmDex->pHeader->stringIdsSize * sizeof(struct StringObject*); 1925bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev totalSize += pDvmDex->pHeader->typeIdsSize * sizeof(struct ClassObject*); 1935bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev totalSize += pDvmDex->pHeader->methodIdsSize * sizeof(struct Method*); 1945bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev totalSize += pDvmDex->pHeader->fieldIdsSize * sizeof(struct Field*); 1955bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev totalSize += sizeof(DvmDex); 1965bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev 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 dvmFreeAtomicCache(pDvmDex->pInterfaceCache); 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sysReleaseShmem(&pDvmDex->memMap); 2025bac60aaafca855f68e1f8b5527d4a4b7897f234Iliyan Malchev munmap(pDvmDex, totalSize); 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 20596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 20696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 20796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Change the byte at the specified address to a new value. If the location 20896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * already has the new value, do nothing. 20996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 21096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * This requires changing the access permissions to read-write, updating 21196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * the value, and then resetting the permissions. 21296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 213fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We need to ensure mutual exclusion at a page granularity to avoid a race 214fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * where one threads sets read-write, another thread sets read-only, and 215fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * then the first thread does a write. Since we don't do a lot of updates, 216fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * and the window is small, we just use a lock across the entire DvmDex. 217fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We're only trying to make the page state change atomic; it's up to the 218fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * caller to ensure that multiple threads aren't stomping on the same 219fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * location (e.g. breakpoints and verifier/optimizer changes happening 220fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * simultaneously). 22196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 22296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * TODO: if we're back to the original state of the page, use 22396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * madvise(MADV_DONTNEED) to release the private/dirty copy. 22496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 22596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" on success. 22696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 22796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenbool dvmDexChangeDex1(DvmDex* pDvmDex, u1* addr, u1 newVal) 22896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 22996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (*addr == newVal) { 23092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ byte at %p is already 0x%02x", addr, newVal); 23196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 23296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 23396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 234fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden /* 235fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We're not holding this for long, so we don't bother with switching 236fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * to VMWAIT. 237fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden */ 238fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmLockMutex(&pDvmDex->modLock); 239fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 24092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ change byte at %p from 0x%02x to 0x%02x", addr, *addr, newVal); 241b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 1, true, &pDvmDex->memMap) != 0) { 242062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("NOTE: DEX page access change (->RW) failed"); 243b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going (may crash) */ 24496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 24596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 24696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *addr = newVal; 24796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 248b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 1, false, &pDvmDex->memMap) != 0) { 249062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("NOTE: DEX page access change (->RO) failed"); 250b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going */ 25196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 25296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 253fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmUnlockMutex(&pDvmDex->modLock); 254fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 25596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 25696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 25796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 25896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden/* 25996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Change the 2-byte value at the specified address to a new value. If the 26096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * location already has the new value, do nothing. 26196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * 26296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Otherwise works like dvmDexChangeDex1. 26396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */ 26496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenbool dvmDexChangeDex2(DvmDex* pDvmDex, u2* addr, u2 newVal) 26596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{ 26696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden if (*addr == newVal) { 26792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ value at %p is already 0x%04x", addr, newVal); 26896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 26996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 27096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 271fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden /* 272fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * We're not holding this for long, so we don't bother with switching 273fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden * to VMWAIT. 274fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden */ 275fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmLockMutex(&pDvmDex->modLock); 276fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 27792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ change 2byte at %p from 0x%04x to 0x%04x", addr, *addr, newVal); 278b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 2, true, &pDvmDex->memMap) != 0) { 279062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("NOTE: DEX page access change (->RW) failed"); 280b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going (may crash) */ 28196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 28296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 28396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *addr = newVal; 28496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 285b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden if (sysChangeMapAccess(addr, 2, false, &pDvmDex->memMap) != 0) { 286062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("NOTE: DEX page access change (->RO) failed"); 287b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden /* expected on files mounted from FAT; keep going */ 28896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden } 28996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden 290fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmUnlockMutex(&pDvmDex->modLock); 291fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden 29296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden return true; 29396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden} 294