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 * The VM wraps some additional data structures around the DexFile. These
18 * are defined here.
19 */
20 #ifndef _DALVIK_DVMDEX
21 #define _DALVIK_DVMDEX
22
23 #include "libdex/DexFile.h"
24
25 /* extern */
26 struct ClassObject;
27 struct HashTable;
28 struct InstField;
29 struct Method;
30 struct StringObject;
31
32
33 /*
34 * Some additional VM data structures that are associated with the DEX file.
35 */
36 typedef struct DvmDex {
37 /* pointer to the DexFile we're associated with */
38 DexFile* pDexFile;
39
40 /* clone of pDexFile->pHeader (it's used frequently enough) */
41 const DexHeader* pHeader;
42
43 /* interned strings; parallel to "stringIds" */
44 struct StringObject** pResStrings;
45
46 /* resolved classes; parallel to "typeIds" */
47 struct ClassObject** pResClasses;
48
49 /* resolved methods; parallel to "methodIds" */
50 struct Method** pResMethods;
51
52 /* resolved instance fields; parallel to "fieldIds" */
53 /* (this holds both InstField and StaticField) */
54 struct Field** pResFields;
55
56 /* interface method lookup cache */
57 struct AtomicCache* pInterfaceCache;
58
59 /* shared memory region with file contents */
60 MemMapping memMap;
61 } DvmDex;
62
63
64 /*
65 * Given a file descriptor for an open "optimized" DEX file, map it into
66 * memory and parse the contents.
67 *
68 * On success, returns 0 and sets "*ppDvmDex" to a newly-allocated DvmDex.
69 * On failure, returns a meaningful error code [currently just -1].
70 */
71 int dvmDexFileOpenFromFd(int fd, DvmDex** ppDvmDex);
72
73 /*
74 * Open a partial DEX file. Only useful as part of the optimization process.
75 */
76 int dvmDexFileOpenPartial(const void* addr, int len, DvmDex** ppDvmDex);
77
78 /*
79 * Free a DvmDex structure, along with any associated structures.
80 */
81 void dvmDexFileFree(DvmDex* pDvmDex);
82
83
84 #if DVM_RESOLVER_CACHE == DVM_RC_DISABLED
85 /* 1:1 mapping */
86
87 /*
88 * Return the requested item if it has been resolved, or NULL if it hasn't.
89 */
dvmDexGetResolvedString(const DvmDex * pDvmDex,u4 stringIdx)90 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
91 u4 stringIdx)
92 {
93 assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
94 return pDvmDex->pResStrings[stringIdx];
95 }
dvmDexGetResolvedClass(const DvmDex * pDvmDex,u4 classIdx)96 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
97 u4 classIdx)
98 {
99 assert(classIdx < pDvmDex->pHeader->typeIdsSize);
100 return pDvmDex->pResClasses[classIdx];
101 }
dvmDexGetResolvedMethod(const DvmDex * pDvmDex,u4 methodIdx)102 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
103 u4 methodIdx)
104 {
105 assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
106 return pDvmDex->pResMethods[methodIdx];
107 }
dvmDexGetResolvedField(const DvmDex * pDvmDex,u4 fieldIdx)108 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
109 u4 fieldIdx)
110 {
111 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
112 return pDvmDex->pResFields[fieldIdx];
113 }
114
115 /*
116 * Update the resolved item table. Resolution always produces the same
117 * result, so we're not worried about atomicity here.
118 */
dvmDexSetResolvedString(DvmDex * pDvmDex,u4 stringIdx,struct StringObject * str)119 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
120 struct StringObject* str)
121 {
122 assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
123 pDvmDex->pResStrings[stringIdx] = str;
124 }
dvmDexSetResolvedClass(DvmDex * pDvmDex,u4 classIdx,struct ClassObject * clazz)125 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
126 struct ClassObject* clazz)
127 {
128 assert(classIdx < pDvmDex->pHeader->typeIdsSize);
129 pDvmDex->pResClasses[classIdx] = clazz;
130 }
dvmDexSetResolvedMethod(DvmDex * pDvmDex,u4 methodIdx,struct Method * method)131 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
132 struct Method* method)
133 {
134 assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
135 pDvmDex->pResMethods[methodIdx] = method;
136 }
dvmDexSetResolvedField(DvmDex * pDvmDex,u4 fieldIdx,struct Field * field)137 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
138 struct Field* field)
139 {
140 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
141 pDvmDex->pResFields[fieldIdx] = field;
142 }
143
144 #elif DVM_RESOLVER_CACHE == DVM_RC_REDUCING
145 /* reduce request to fit in a less-than-full-size cache table */
146
147 /*
148 * Return the requested item if it has been resolved, or NULL if it hasn't.
149 *
150 * If we have a mapping table defined for this category, but there's no
151 * entry for this index, we always return NULL. Otherwise, we return the
152 * entry. (To regain some performance we may want to assume that the
153 * table exists when compiled in this mode -- avoids a null check but
154 * prevents us from switching back and forth without rebuilding the VM.)
155 *
156 * We could save an integer compare here by ensuring that map[kNoIndexMapping]
157 * always evalutes to NULL (e.g. set kNoIndexMapping = 0).
158 */
dvmDexGetResolvedString(const DvmDex * pDvmDex,u4 stringIdx)159 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
160 u4 stringIdx)
161 {
162 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
163
164 assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
165 if (pIndexMap->stringReducedCount > 0) {
166 stringIdx = pIndexMap->stringMap[stringIdx];
167 if (stringIdx == kNoIndexMapping)
168 return NULL;
169 }
170 return pDvmDex->pResStrings[stringIdx];
171 }
dvmDexGetResolvedClass(const DvmDex * pDvmDex,u4 classIdx)172 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
173 u4 classIdx)
174 {
175 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
176
177 assert(classIdx < pDvmDex->pHeader->typeIdsSize);
178 if (pIndexMap->classReducedCount > 0) {
179 classIdx = pIndexMap->classMap[classIdx];
180 if (classIdx == kNoIndexMapping)
181 return NULL;
182 }
183 return pDvmDex->pResClasses[classIdx];
184 }
dvmDexGetResolvedMethod(const DvmDex * pDvmDex,u4 methodIdx)185 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
186 u4 methodIdx)
187 {
188 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
189
190 assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
191 if (pIndexMap->methodReducedCount > 0) {
192 methodIdx = pIndexMap->methodMap[methodIdx];
193 if (methodIdx == kNoIndexMapping)
194 return NULL;
195 }
196 return pDvmDex->pResMethods[methodIdx];
197 }
dvmDexGetResolvedField(const DvmDex * pDvmDex,u4 fieldIdx)198 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
199 u4 fieldIdx)
200 {
201 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
202
203 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
204 if (pIndexMap->fieldReducedCount > 0) {
205 fieldIdx = pIndexMap->fieldMap[fieldIdx];
206 if (fieldIdx == kNoIndexMapping)
207 return NULL;
208 }
209 return pDvmDex->pResFields[fieldIdx];
210 }
211
212 /*
213 * Update the resolved item table. Resolution always produces the same
214 * result, so we're not worried about atomicity here.
215 */
dvmDexSetResolvedString(DvmDex * pDvmDex,u4 stringIdx,struct StringObject * str)216 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
217 struct StringObject* str)
218 {
219 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
220 u4 newIdx;
221
222 assert(stringIdx < pDvmDex->pHeader->stringIdsSize);
223 if (pIndexMap->stringReducedCount > 0) {
224 newIdx = pIndexMap->stringMap[stringIdx];
225 if (newIdx != kNoIndexMapping)
226 pDvmDex->pResStrings[newIdx] = str;
227 }
228 }
dvmDexSetResolvedClass(DvmDex * pDvmDex,u4 classIdx,struct ClassObject * clazz)229 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
230 struct ClassObject* clazz)
231 {
232 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
233 u4 newIdx;
234
235 assert(classIdx < pDvmDex->pHeader->typeIdsSize);
236 if (pIndexMap->classReducedCount > 0) {
237 newIdx = pIndexMap->classMap[classIdx];
238 if (newIdx != kNoIndexMapping)
239 pDvmDex->pResClasses[newIdx] = clazz;
240 }
241 }
dvmDexSetResolvedMethod(DvmDex * pDvmDex,u4 methodIdx,struct Method * method)242 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
243 struct Method* method)
244 {
245 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
246 u4 newIdx;
247
248 assert(methodIdx < pDvmDex->pHeader->methodIdsSize);
249 if (pIndexMap->methodReducedCount > 0) {
250 newIdx = pIndexMap->methodMap[methodIdx];
251 if (newIdx != kNoIndexMapping)
252 pDvmDex->pResMethods[newIdx] = method;
253 }
254 }
dvmDexSetResolvedField(DvmDex * pDvmDex,u4 fieldIdx,struct Field * field)255 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
256 struct Field* field)
257 {
258 const DexIndexMap* pIndexMap = &pDvmDex->pDexFile->indexMap;
259 u4 newIdx;
260
261 assert(fieldIdx < pDvmDex->pHeader->fieldIdsSize);
262 if (pIndexMap->fieldReducedCount > 0) {
263 newIdx = pIndexMap->fieldMap[fieldIdx];
264 if (newIdx != kNoIndexMapping)
265 pDvmDex->pResFields[newIdx] = field;
266 }
267 }
268
269 #elif DVM_RESOLVER_CACHE == DVM_RC_EXPANDING
270
271 #error "not implemented" /* TODO */
272
273 #elif DVM_RESOLVER_CACHE == DVM_RC_NO_CACHE
274
275 /*
276 * There's no cache, so we always return NULL.
277 */
dvmDexGetResolvedString(const DvmDex * pDvmDex,u4 stringIdx)278 INLINE struct StringObject* dvmDexGetResolvedString(const DvmDex* pDvmDex,
279 u4 stringIdx)
280 {
281 return NULL;
282 }
dvmDexGetResolvedClass(const DvmDex * pDvmDex,u4 classIdx)283 INLINE struct ClassObject* dvmDexGetResolvedClass(const DvmDex* pDvmDex,
284 u4 classIdx)
285 {
286 return NULL;
287 }
dvmDexGetResolvedMethod(const DvmDex * pDvmDex,u4 methodIdx)288 INLINE struct Method* dvmDexGetResolvedMethod(const DvmDex* pDvmDex,
289 u4 methodIdx)
290 {
291 return NULL;
292 }
dvmDexGetResolvedField(const DvmDex * pDvmDex,u4 fieldIdx)293 INLINE struct Field* dvmDexGetResolvedField(const DvmDex* pDvmDex,
294 u4 fieldIdx)
295 {
296 return NULL;
297 }
298
299 /*
300 * Update the resolved item table. There is no table, so do nothing.
301 */
dvmDexSetResolvedString(DvmDex * pDvmDex,u4 stringIdx,struct StringObject * str)302 INLINE void dvmDexSetResolvedString(DvmDex* pDvmDex, u4 stringIdx,
303 struct StringObject* str)
304 {}
dvmDexSetResolvedClass(DvmDex * pDvmDex,u4 classIdx,struct ClassObject * clazz)305 INLINE void dvmDexSetResolvedClass(DvmDex* pDvmDex, u4 classIdx,
306 struct ClassObject* clazz)
307 {}
dvmDexSetResolvedMethod(DvmDex * pDvmDex,u4 methodIdx,struct Method * method)308 INLINE void dvmDexSetResolvedMethod(DvmDex* pDvmDex, u4 methodIdx,
309 struct Method* method)
310 {}
dvmDexSetResolvedField(DvmDex * pDvmDex,u4 fieldIdx,struct Field * field)311 INLINE void dvmDexSetResolvedField(DvmDex* pDvmDex, u4 fieldIdx,
312 struct Field* field)
313 {}
314
315 #else
316 #error "huh?"
317 #endif /*DVM_RESOLVER_CACHE==N*/
318
319 #endif /*_DALVIK_DVMDEX*/
320