1 /*
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 */
allocateAuxStructures(DexFile * pDexFile)38 static 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 */
dvmDexFileOpenFromFd(int fd,DvmDex ** ppDvmDex)115 int 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
155 bail:
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 */
dvmDexFileOpenPartial(const void * addr,int len,DvmDex ** ppDvmDex)167 int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex)
168 {
169 DvmDex* pDvmDex;
170 DexFile* pDexFile;
171 int parseFlags = kDexParseDefault;
172 int result = -1;
173
174 if (gDvm.verifyDexChecksum)
175 parseFlags |= kDexParseVerifyChecksum;
176
177 pDexFile = dexFileParse(addr, len, parseFlags);
178 if (pDexFile == NULL) {
179 LOGE("DEX parse failed\n");
180 goto bail;
181 }
182 pDvmDex = allocateAuxStructures(pDexFile);
183 if (pDvmDex == NULL) {
184 dexFileFree(pDexFile);
185 goto bail;
186 }
187
188 *ppDvmDex = pDvmDex;
189 result = 0;
190
191 bail:
192 return result;
193 }
194
195 /*
196 * Free up the DexFile and any associated data structures.
197 *
198 * Note we may be called with a partially-initialized DvmDex.
199 */
dvmDexFileFree(DvmDex * pDvmDex)200 void dvmDexFileFree(DvmDex* pDvmDex)
201 {
202 if (pDvmDex == NULL)
203 return;
204
205 dexFileFree(pDvmDex->pDexFile);
206
207 LOGV("+++ DEX %p: freeing aux structs\n", pDvmDex);
208 free(pDvmDex->pResStrings);
209 free(pDvmDex->pResClasses);
210 free(pDvmDex->pResMethods);
211 free(pDvmDex->pResFields);
212 dvmFreeAtomicCache(pDvmDex->pInterfaceCache);
213
214 sysReleaseShmem(&pDvmDex->memMap);
215 free(pDvmDex);
216 }
217
218