DvmDex.cpp revision b5ebe47515c9750c7347557075d3714ba7671aa9
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 *
23096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * This does not make any synchronization guarantees.  It's important for the
23196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * caller(s) to work out mutual exclusion, at least on a page granularity,
23296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * to avoid a race where one threads sets read-write, another thread sets
23396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * read-only, and then the first thread does a write.
23496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
23596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * TODO: if we're back to the original state of the page, use
23696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * madvise(MADV_DONTNEED) to release the private/dirty copy.
23796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden *
23896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden * Returns "true" on success.
23996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden */
24096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFaddenbool dvmDexChangeDex1(DvmDex* pDvmDex, u1* addr, u1 newVal)
24196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden{
24296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    if (*addr == newVal) {
24396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        LOGV("+++ byte at %p is already 0x%02x\n", addr, newVal);
24496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        return true;
24596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
24696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
24796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    LOGV("+++ change byte at %p from 0x%02x to 0x%02x\n", addr, *addr, newVal);
248b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden    if (sysChangeMapAccess(addr, 1, true, &pDvmDex->memMap) != 0) {
249b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden        LOGD("NOTE: DEX page access change (->RW) failed\n");
250b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden        /* expected on files mounted from FAT; keep going (may crash) */
25196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
25296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
25396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    *addr = newVal;
25496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
255b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden    if (sysChangeMapAccess(addr, 1, false, &pDvmDex->memMap) != 0) {
256b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden        LOGD("NOTE: DEX page access change (->RO) failed\n");
257b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden        /* expected on files mounted from FAT; keep going */
25896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
25996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy 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) {
27296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        LOGV("+++ value at %p is already 0x%04x\n", addr, newVal);
27396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden        return true;
27496516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
27596516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
27696516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    LOGV("+++ change 2byte at %p from 0x%04x to 0x%04x\n", addr, *addr, newVal);
277b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden    if (sysChangeMapAccess(addr, 2, true, &pDvmDex->memMap) != 0) {
278b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden        LOGD("NOTE: DEX page access change (->RW) failed\n");
279b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden        /* expected on files mounted from FAT; keep going (may crash) */
28096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
28196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
28296516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    *addr = newVal;
28396516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
284b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden    if (sysChangeMapAccess(addr, 2, false, &pDvmDex->memMap) != 0) {
285b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden        LOGD("NOTE: DEX page access change (->RO) failed\n");
286b5ebe47515c9750c7347557075d3714ba7671aa9Andy McFadden        /* expected on files mounted from FAT; keep going */
28796516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    }
28896516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
28996516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden    return true;
29096516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden}
29196516932f1557d8f48a8b2dbbb885af01a11ef6eAndy McFadden
292