blob: 6740632b3c7b04d7a3be075989e4f62ea092e2bd [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16/*
17 * VM-specific state associated with a DEX file.
18 */
19#include "Dalvik.h"
20
21/*
22 * Create auxillary data structures.
23 *
24 * We need a 4-byte pointer for every reference to a class, method, field,
25 * or string constant. Summed up over all loaded DEX files (including the
26 * whoppers in the boostrap class path), this adds up to be quite a bit
27 * of native memory.
28 *
29 * For more traditional VMs these values could be stuffed into the loaded
30 * class file constant pool area, but we don't have that luxury since our
31 * classes are memory-mapped read-only.
32 *
33 * The DEX optimizer will remove the need for some of these (e.g. we won't
34 * use the entry for virtual methods that are only called through
35 * invoke-virtual-quick), creating the possibility of some space reduction
36 * at dexopt time.
37 */
38static DvmDex* allocateAuxStructures(DexFile* pDexFile)
39{
40 DvmDex* pDvmDex;
41 const DexHeader* pHeader;
42 u4 stringCount, classCount, methodCount, fieldCount;
43
44 pDvmDex = (DvmDex*) calloc(1, sizeof(DvmDex));
45 if (pDvmDex == NULL)
46 return NULL;
47
48 pDvmDex->pDexFile = pDexFile;
49 pDvmDex->pHeader = pDexFile->pHeader;
50
51 pHeader = pDvmDex->pHeader;
52
53 stringCount = pHeader->stringIdsSize;
54 classCount = pHeader->typeIdsSize;
55 methodCount = pHeader->methodIdsSize;
56 fieldCount = pHeader->fieldIdsSize;
57
58#if (DVM_RESOLVER_CACHE == DVM_RC_REDUCING) || \
59 (DVM_RESOLVER_CACHE == DVM_RC_EXPANDING)
60 if (pDexFile->indexMap.stringReducedCount > 0)
61 stringCount = pDexFile->indexMap.stringReducedCount;
62 if (pDexFile->indexMap.classReducedCount > 0)
63 classCount = pDexFile->indexMap.classReducedCount;
64 if (pDexFile->indexMap.methodReducedCount > 0)
65 methodCount = pDexFile->indexMap.methodReducedCount;
66 if (pDexFile->indexMap.fieldReducedCount > 0)
67 fieldCount = pDexFile->indexMap.fieldReducedCount;
68#elif (DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE)
69 stringCount = classCount = methodCount = fieldCount = 0;
70#endif
71
72 pDvmDex->pResStrings = (struct StringObject**)
73 calloc(stringCount, sizeof(struct StringObject*));
74
75 pDvmDex->pResClasses = (struct ClassObject**)
76 calloc(classCount, sizeof(struct ClassObject*));
77
78 pDvmDex->pResMethods = (struct Method**)
79 calloc(methodCount, sizeof(struct Method*));
80
81 pDvmDex->pResFields = (struct Field**)
82 calloc(fieldCount, sizeof(struct Field*));
83
84 LOGV("+++ DEX %p: allocateAux %d+%d+%d+%d * 4 = %d bytes\n",
85 pDvmDex, stringCount, classCount, methodCount, fieldCount,
86 (stringCount + classCount + methodCount + fieldCount) * 4);
87
88 pDvmDex->pInterfaceCache = dvmAllocAtomicCache(DEX_INTERFACE_CACHE_SIZE);
89
90 if (pDvmDex->pResStrings == NULL ||
91 pDvmDex->pResClasses == NULL ||
92 pDvmDex->pResMethods == NULL ||
93 pDvmDex->pResFields == NULL ||
94 pDvmDex->pInterfaceCache == NULL)
95 {
96 LOGE("Alloc failure in allocateAuxStructures\n");
97 free(pDvmDex->pResStrings);
98 free(pDvmDex->pResClasses);
99 free(pDvmDex->pResMethods);
100 free(pDvmDex->pResFields);
101 free(pDvmDex);
102 return NULL;
103 }
104
105 return pDvmDex;
106
107}
108
109/*
110 * Given an open optimized DEX file, map it into read-only shared memory and
111 * parse the contents.
112 *
113 * Returns nonzero on error.
114 */
115int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex)
116{
117 DvmDex* pDvmDex;
118 DexFile* pDexFile;
119 MemMapping memMap;
120 int parseFlags = kDexParseDefault;
121 int result = -1;
122
123 if (gDvm.verifyDexChecksum)
124 parseFlags |= kDexParseVerifyChecksum;
125
126 if (lseek(fd, 0, SEEK_SET) < 0) {
127 LOGE("lseek rewind failed\n");
128 goto bail;
129 }
130
131 if (sysMapFileInShmem(fd, &memMap) != 0) {
132 LOGE("Unable to map file\n");
133 goto bail;
134 }
135
136 pDexFile = dexFileParse(memMap.addr, memMap.length, parseFlags);
137 if (pDexFile == NULL) {
138 LOGE("DEX parse failed\n");
139 sysReleaseShmem(&memMap);
140 goto bail;
141 }
142
143 pDvmDex = allocateAuxStructures(pDexFile);
144 if (pDvmDex == NULL) {
145 dexFileFree(pDexFile);
146 sysReleaseShmem(&memMap);
147 goto bail;
148 }
149
150 /* tuck this into the DexFile so it gets released later */
151 sysCopyMap(&pDvmDex->memMap, &memMap);
152 *ppDvmDex = pDvmDex;
153 result = 0;
154
155bail:
156 return result;
157}
158
159/*
160 * Create a DexFile structure for a "partial" DEX. This is one that is in
161 * the process of being optimized. The optimization header isn't finished
162 * and we won't have any of the auxillary data tables, so we have to do
163 * the initialization slightly differently.
164 *
165 * Returns nonzero on error.
166 */
167int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
168{
169 DvmDex* pDvmDex;
170 DexFile* pDexFile;
171 int parseFlags = kDexParseDefault;
172 int result = -1;
173
Andy McFaddene1f560a2009-04-02 10:58:14 -0700174 /* -- file is incomplete, new checksum has not yet been calculated
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800175 if (gDvm.verifyDexChecksum)
176 parseFlags |= kDexParseVerifyChecksum;
Andy McFaddene1f560a2009-04-02 10:58:14 -0700177 */
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800178
179 pDexFile = dexFileParse(addr, len, parseFlags);
180 if (pDexFile == NULL) {
181 LOGE("DEX parse failed\n");
182 goto bail;
183 }
184 pDvmDex = allocateAuxStructures(pDexFile);
185 if (pDvmDex == NULL) {
186 dexFileFree(pDexFile);
187 goto bail;
188 }
189
190 *ppDvmDex = pDvmDex;
191 result = 0;
192
193bail:
194 return result;
195}
196
197/*
198 * Free up the DexFile and any associated data structures.
199 *
200 * Note we may be called with a partially-initialized DvmDex.
201 */
202void dvmDexFileFree(DvmDex* pDvmDex)
203{
204 if (pDvmDex == NULL)
205 return;
206
207 dexFileFree(pDvmDex->pDexFile);
208
209 LOGV("+++ DEX %p: freeing aux structs\n", pDvmDex);
210 free(pDvmDex->pResStrings);
211 free(pDvmDex->pResClasses);
212 free(pDvmDex->pResMethods);
213 free(pDvmDex->pResFields);
214 dvmFreeAtomicCache(pDvmDex->pInterfaceCache);
215
216 sysReleaseShmem(&pDvmDex->memMap);
217 free(pDvmDex);
218}
219