OSDN Git Service

Merge "Fix synchronization when preparing ids." into klp-dev
[android-x86/dalvik.git] / libdex / DexFile.cpp
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 /*
18  * Access the contents of a .dex file.
19  */
20
21 #include "DexFile.h"
22 #include "DexOptData.h"
23 #include "DexProto.h"
24 #include "DexCatch.h"
25 #include "Leb128.h"
26 #include "sha1.h"
27 #include "ZipArchive.h"
28
29 #include <zlib.h>
30
31 #include <stdlib.h>
32 #include <stddef.h>
33 #include <string.h>
34 #include <fcntl.h>
35 #include <errno.h>
36
37
38 /*
39  * Verifying checksums is good, but it slows things down and causes us to
40  * touch every page.  In the "optimized" world, it doesn't work at all,
41  * because we rewrite the contents.
42  */
43 static const bool kVerifyChecksum = false;
44 static const bool kVerifySignature = false;
45
46 /* (documented in header) */
47 char dexGetPrimitiveTypeDescriptorChar(PrimitiveType type) {
48     const char* string = dexGetPrimitiveTypeDescriptor(type);
49
50     return (string == NULL) ? '\0' : string[0];
51 }
52
53 /* (documented in header) */
54 const char* dexGetPrimitiveTypeDescriptor(PrimitiveType type) {
55     switch (type) {
56         case PRIM_VOID:    return "V";
57         case PRIM_BOOLEAN: return "Z";
58         case PRIM_BYTE:    return "B";
59         case PRIM_SHORT:   return "S";
60         case PRIM_CHAR:    return "C";
61         case PRIM_INT:     return "I";
62         case PRIM_LONG:    return "J";
63         case PRIM_FLOAT:   return "F";
64         case PRIM_DOUBLE:  return "D";
65         default:           return NULL;
66     }
67
68     return NULL;
69 }
70
71 /* (documented in header) */
72 const char* dexGetBoxedTypeDescriptor(PrimitiveType type) {
73     switch (type) {
74         case PRIM_VOID:    return NULL;
75         case PRIM_BOOLEAN: return "Ljava/lang/Boolean;";
76         case PRIM_BYTE:    return "Ljava/lang/Byte;";
77         case PRIM_SHORT:   return "Ljava/lang/Short;";
78         case PRIM_CHAR:    return "Ljava/lang/Character;";
79         case PRIM_INT:     return "Ljava/lang/Integer;";
80         case PRIM_LONG:    return "Ljava/lang/Long;";
81         case PRIM_FLOAT:   return "Ljava/lang/Float;";
82         case PRIM_DOUBLE:  return "Ljava/lang/Double;";
83         default:           return NULL;
84     }
85 }
86
87 /* (documented in header) */
88 PrimitiveType dexGetPrimitiveTypeFromDescriptorChar(char descriptorChar) {
89     switch (descriptorChar) {
90         case 'V': return PRIM_VOID;
91         case 'Z': return PRIM_BOOLEAN;
92         case 'B': return PRIM_BYTE;
93         case 'S': return PRIM_SHORT;
94         case 'C': return PRIM_CHAR;
95         case 'I': return PRIM_INT;
96         case 'J': return PRIM_LONG;
97         case 'F': return PRIM_FLOAT;
98         case 'D': return PRIM_DOUBLE;
99         default:  return PRIM_NOT;
100     }
101 }
102
103 /* Return the UTF-8 encoded string with the specified string_id index,
104  * also filling in the UTF-16 size (number of 16-bit code points).*/
105 const char* dexStringAndSizeById(const DexFile* pDexFile, u4 idx,
106         u4* utf16Size) {
107     const DexStringId* pStringId = dexGetStringId(pDexFile, idx);
108     const u1* ptr = pDexFile->baseAddr + pStringId->stringDataOff;
109
110     *utf16Size = readUnsignedLeb128(&ptr);
111     return (const char*) ptr;
112 }
113
114 /*
115  * Format an SHA-1 digest for printing.  tmpBuf must be able to hold at
116  * least kSHA1DigestOutputLen bytes.
117  */
118 const char* dvmSHA1DigestToStr(const unsigned char digest[], char* tmpBuf);
119
120 /*
121  * Compute a SHA-1 digest on a range of bytes.
122  */
123 static void dexComputeSHA1Digest(const unsigned char* data, size_t length,
124     unsigned char digest[])
125 {
126     SHA1_CTX context;
127     SHA1Init(&context);
128     SHA1Update(&context, data, length);
129     SHA1Final(digest, &context);
130 }
131
132 /*
133  * Format the SHA-1 digest into the buffer, which must be able to hold at
134  * least kSHA1DigestOutputLen bytes.  Returns a pointer to the buffer,
135  */
136 static const char* dexSHA1DigestToStr(const unsigned char digest[],char* tmpBuf)
137 {
138     static const char hexDigit[] = "0123456789abcdef";
139     char* cp;
140     int i;
141
142     cp = tmpBuf;
143     for (i = 0; i < kSHA1DigestLen; i++) {
144         *cp++ = hexDigit[digest[i] >> 4];
145         *cp++ = hexDigit[digest[i] & 0x0f];
146     }
147     *cp++ = '\0';
148
149     assert(cp == tmpBuf + kSHA1DigestOutputLen);
150
151     return tmpBuf;
152 }
153
154 /*
155  * Compute a hash code on a UTF-8 string, for use with internal hash tables.
156  *
157  * This may or may not be compatible with UTF-8 hash functions used inside
158  * the Dalvik VM.
159  *
160  * The basic "multiply by 31 and add" approach does better on class names
161  * than most other things tried (e.g. adler32).
162  */
163 static u4 classDescriptorHash(const char* str)
164 {
165     u4 hash = 1;
166
167     while (*str != '\0')
168         hash = hash * 31 + *str++;
169
170     return hash;
171 }
172
173 /*
174  * Add an entry to the class lookup table.  We hash the string and probe
175  * until we find an open slot.
176  */
177 static void classLookupAdd(DexFile* pDexFile, DexClassLookup* pLookup,
178     int stringOff, int classDefOff, int* pNumProbes)
179 {
180     const char* classDescriptor =
181         (const char*) (pDexFile->baseAddr + stringOff);
182     const DexClassDef* pClassDef =
183         (const DexClassDef*) (pDexFile->baseAddr + classDefOff);
184     u4 hash = classDescriptorHash(classDescriptor);
185     int mask = pLookup->numEntries-1;
186     int idx = hash & mask;
187
188     /*
189      * Find the first empty slot.  We oversized the table, so this is
190      * guaranteed to finish.
191      */
192     int probes = 0;
193     while (pLookup->table[idx].classDescriptorOffset != 0) {
194         idx = (idx + 1) & mask;
195         probes++;
196     }
197     //if (probes > 1)
198     //    ALOGW("classLookupAdd: probes=%d", probes);
199
200     pLookup->table[idx].classDescriptorHash = hash;
201     pLookup->table[idx].classDescriptorOffset = stringOff;
202     pLookup->table[idx].classDefOffset = classDefOff;
203     *pNumProbes = probes;
204 }
205
206 /*
207  * Create the class lookup hash table.
208  *
209  * Returns newly-allocated storage.
210  */
211 DexClassLookup* dexCreateClassLookup(DexFile* pDexFile)
212 {
213     DexClassLookup* pLookup;
214     int allocSize;
215     int i, numEntries;
216     int numProbes, totalProbes, maxProbes;
217
218     numProbes = totalProbes = maxProbes = 0;
219
220     assert(pDexFile != NULL);
221
222     /*
223      * Using a factor of 3 results in far less probing than a factor of 2,
224      * but almost doubles the flash storage requirements for the bootstrap
225      * DEX files.  The overall impact on class loading performance seems
226      * to be minor.  We could probably get some performance improvement by
227      * using a secondary hash.
228      */
229     numEntries = dexRoundUpPower2(pDexFile->pHeader->classDefsSize * 2);
230     allocSize = offsetof(DexClassLookup, table)
231                     + numEntries * sizeof(pLookup->table[0]);
232
233     pLookup = (DexClassLookup*) calloc(1, allocSize);
234     if (pLookup == NULL)
235         return NULL;
236     pLookup->size = allocSize;
237     pLookup->numEntries = numEntries;
238
239     for (i = 0; i < (int)pDexFile->pHeader->classDefsSize; i++) {
240         const DexClassDef* pClassDef;
241         const char* pString;
242
243         pClassDef = dexGetClassDef(pDexFile, i);
244         pString = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
245
246         classLookupAdd(pDexFile, pLookup,
247             (u1*)pString - pDexFile->baseAddr,
248             (u1*)pClassDef - pDexFile->baseAddr, &numProbes);
249
250         if (numProbes > maxProbes)
251             maxProbes = numProbes;
252         totalProbes += numProbes;
253     }
254
255     ALOGV("Class lookup: classes=%d slots=%d (%d%% occ) alloc=%d"
256          " total=%d max=%d",
257         pDexFile->pHeader->classDefsSize, numEntries,
258         (100 * pDexFile->pHeader->classDefsSize) / numEntries,
259         allocSize, totalProbes, maxProbes);
260
261     return pLookup;
262 }
263
264
265 /*
266  * Set up the basic raw data pointers of a DexFile. This function isn't
267  * meant for general use.
268  */
269 void dexFileSetupBasicPointers(DexFile* pDexFile, const u1* data) {
270     DexHeader *pHeader = (DexHeader*) data;
271
272     pDexFile->baseAddr = data;
273     pDexFile->pHeader = pHeader;
274     pDexFile->pStringIds = (const DexStringId*) (data + pHeader->stringIdsOff);
275     pDexFile->pTypeIds = (const DexTypeId*) (data + pHeader->typeIdsOff);
276     pDexFile->pFieldIds = (const DexFieldId*) (data + pHeader->fieldIdsOff);
277     pDexFile->pMethodIds = (const DexMethodId*) (data + pHeader->methodIdsOff);
278     pDexFile->pProtoIds = (const DexProtoId*) (data + pHeader->protoIdsOff);
279     pDexFile->pClassDefs = (const DexClassDef*) (data + pHeader->classDefsOff);
280     pDexFile->pLinkData = (const DexLink*) (data + pHeader->linkOff);
281 }
282
283 /*
284  * Parse an optimized or unoptimized .dex file sitting in memory.  This is
285  * called after the byte-ordering and structure alignment has been fixed up.
286  *
287  * On success, return a newly-allocated DexFile.
288  */
289 DexFile* dexFileParse(const u1* data, size_t length, int flags)
290 {
291     DexFile* pDexFile = NULL;
292     const DexHeader* pHeader;
293     const u1* magic;
294     int result = -1;
295
296     if (length < sizeof(DexHeader)) {
297         ALOGE("too short to be a valid .dex");
298         goto bail;      /* bad file format */
299     }
300
301     pDexFile = (DexFile*) malloc(sizeof(DexFile));
302     if (pDexFile == NULL)
303         goto bail;      /* alloc failure */
304     memset(pDexFile, 0, sizeof(DexFile));
305
306     /*
307      * Peel off the optimized header.
308      */
309     if (memcmp(data, DEX_OPT_MAGIC, 4) == 0) {
310         magic = data;
311         if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) {
312             ALOGE("bad opt version (0x%02x %02x %02x %02x)",
313                  magic[4], magic[5], magic[6], magic[7]);
314             goto bail;
315         }
316
317         pDexFile->pOptHeader = (const DexOptHeader*) data;
318         ALOGV("Good opt header, DEX offset is %d, flags=0x%02x",
319             pDexFile->pOptHeader->dexOffset, pDexFile->pOptHeader->flags);
320
321         /* parse the optimized dex file tables */
322         if (!dexParseOptData(data, length, pDexFile))
323             goto bail;
324
325         /* ignore the opt header and appended data from here on out */
326         data += pDexFile->pOptHeader->dexOffset;
327         length -= pDexFile->pOptHeader->dexOffset;
328         if (pDexFile->pOptHeader->dexLength > length) {
329             ALOGE("File truncated? stored len=%d, rem len=%d",
330                 pDexFile->pOptHeader->dexLength, (int) length);
331             goto bail;
332         }
333         length = pDexFile->pOptHeader->dexLength;
334     }
335
336     dexFileSetupBasicPointers(pDexFile, data);
337     pHeader = pDexFile->pHeader;
338
339     if (!dexHasValidMagic(pHeader)) {
340         goto bail;
341     }
342
343     /*
344      * Verify the checksum(s).  This is reasonably quick, but does require
345      * touching every byte in the DEX file.  The base checksum changes after
346      * byte-swapping and DEX optimization.
347      */
348     if (flags & kDexParseVerifyChecksum) {
349         u4 adler = dexComputeChecksum(pHeader);
350         if (adler != pHeader->checksum) {
351             ALOGE("ERROR: bad checksum (%08x vs %08x)",
352                 adler, pHeader->checksum);
353             if (!(flags & kDexParseContinueOnError))
354                 goto bail;
355         } else {
356             ALOGV("+++ adler32 checksum (%08x) verified", adler);
357         }
358
359         const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
360         if (pOptHeader != NULL) {
361             adler = dexComputeOptChecksum(pOptHeader);
362             if (adler != pOptHeader->checksum) {
363                 ALOGE("ERROR: bad opt checksum (%08x vs %08x)",
364                     adler, pOptHeader->checksum);
365                 if (!(flags & kDexParseContinueOnError))
366                     goto bail;
367             } else {
368                 ALOGV("+++ adler32 opt checksum (%08x) verified", adler);
369             }
370         }
371     }
372
373     /*
374      * Verify the SHA-1 digest.  (Normally we don't want to do this --
375      * the digest is used to uniquely identify the original DEX file, and
376      * can't be computed for verification after the DEX is byte-swapped
377      * and optimized.)
378      */
379     if (kVerifySignature) {
380         unsigned char sha1Digest[kSHA1DigestLen];
381         const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum) +
382                             kSHA1DigestLen;
383
384         dexComputeSHA1Digest(data + nonSum, length - nonSum, sha1Digest);
385         if (memcmp(sha1Digest, pHeader->signature, kSHA1DigestLen) != 0) {
386             char tmpBuf1[kSHA1DigestOutputLen];
387             char tmpBuf2[kSHA1DigestOutputLen];
388             ALOGE("ERROR: bad SHA1 digest (%s vs %s)",
389                 dexSHA1DigestToStr(sha1Digest, tmpBuf1),
390                 dexSHA1DigestToStr(pHeader->signature, tmpBuf2));
391             if (!(flags & kDexParseContinueOnError))
392                 goto bail;
393         } else {
394             ALOGV("+++ sha1 digest verified");
395         }
396     }
397
398     if (pHeader->fileSize != length) {
399         ALOGE("ERROR: stored file size (%d) != expected (%d)",
400             (int) pHeader->fileSize, (int) length);
401         if (!(flags & kDexParseContinueOnError))
402             goto bail;
403     }
404
405     if (pHeader->classDefsSize == 0) {
406         ALOGE("ERROR: DEX file has no classes in it, failing");
407         goto bail;
408     }
409
410     /*
411      * Success!
412      */
413     result = 0;
414
415 bail:
416     if (result != 0 && pDexFile != NULL) {
417         dexFileFree(pDexFile);
418         pDexFile = NULL;
419     }
420     return pDexFile;
421 }
422
423 /*
424  * Free up the DexFile and any associated data structures.
425  *
426  * Note we may be called with a partially-initialized DexFile.
427  */
428 void dexFileFree(DexFile* pDexFile)
429 {
430     if (pDexFile == NULL)
431         return;
432
433     free(pDexFile);
434 }
435
436 /*
437  * Look up a class definition entry by descriptor.
438  *
439  * "descriptor" should look like "Landroid/debug/Stuff;".
440  */
441 const DexClassDef* dexFindClass(const DexFile* pDexFile,
442     const char* descriptor)
443 {
444     const DexClassLookup* pLookup = pDexFile->pClassLookup;
445     u4 hash;
446     int idx, mask;
447
448     hash = classDescriptorHash(descriptor);
449     mask = pLookup->numEntries - 1;
450     idx = hash & mask;
451
452     /*
453      * Search until we find a matching entry or an empty slot.
454      */
455     while (true) {
456         int offset;
457
458         offset = pLookup->table[idx].classDescriptorOffset;
459         if (offset == 0)
460             return NULL;
461
462         if (pLookup->table[idx].classDescriptorHash == hash) {
463             const char* str;
464
465             str = (const char*) (pDexFile->baseAddr + offset);
466             if (strcmp(str, descriptor) == 0) {
467                 return (const DexClassDef*)
468                     (pDexFile->baseAddr + pLookup->table[idx].classDefOffset);
469             }
470         }
471
472         idx = (idx + 1) & mask;
473     }
474 }
475
476
477 /*
478  * Compute the DEX file checksum for a memory-mapped DEX file.
479  */
480 u4 dexComputeChecksum(const DexHeader* pHeader)
481 {
482     const u1* start = (const u1*) pHeader;
483
484     uLong adler = adler32(0L, Z_NULL, 0);
485     const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);
486
487     return (u4) adler32(adler, start + nonSum, pHeader->fileSize - nonSum);
488 }
489
490 /*
491  * Compute the size, in bytes, of a DexCode.
492  */
493 size_t dexGetDexCodeSize(const DexCode* pCode)
494 {
495     /*
496      * The catch handler data is the last entry.  It has a variable number
497      * of variable-size pieces, so we need to create an iterator.
498      */
499     u4 handlersSize;
500     u4 offset;
501     u4 ui;
502
503     if (pCode->triesSize != 0) {
504         handlersSize = dexGetHandlersSize(pCode);
505         offset = dexGetFirstHandlerOffset(pCode);
506     } else {
507         handlersSize = 0;
508         offset = 0;
509     }
510
511     for (ui = 0; ui < handlersSize; ui++) {
512         DexCatchIterator iterator;
513         dexCatchIteratorInit(&iterator, pCode, offset);
514         offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
515     }
516
517     const u1* handlerData = dexGetCatchHandlerData(pCode);
518
519     //ALOGD("+++ pCode=%p handlerData=%p last offset=%d",
520     //    pCode, handlerData, offset);
521
522     /* return the size of the catch handler + everything before it */
523     return (handlerData - (u1*) pCode) + offset;
524 }
525
526 /*
527  * Round up to the next highest power of 2.
528  *
529  * Found on http://graphics.stanford.edu/~seander/bithacks.html.
530  */
531 u4 dexRoundUpPower2(u4 val)
532 {
533     val--;
534     val |= val >> 1;
535     val |= val >> 2;
536     val |= val >> 4;
537     val |= val >> 8;
538     val |= val >> 16;
539     val++;
540
541     return val;
542 }