• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * Prepare a DEX file for use by the VM.  Depending upon the VM options
19  * we will attempt to verify and/or optimize the code, possibly appending
20  * register maps.
21  *
22  * TODO: the format of the optimized header is currently "whatever we
23  * happen to write", since the VM that writes it is by definition the same
24  * as the VM that reads it.  Still, it should be better documented and
25  * more rigorously structured.
26  */
27 #include "Dalvik.h"
28 #include "libdex/OptInvocation.h"
29 #include "analysis/RegisterMap.h"
30 #include "analysis/Optimize.h"
31 
32 #include <zlib.h>
33 
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <sys/mman.h>
37 #include <sys/stat.h>
38 #include <sys/file.h>
39 #include <sys/wait.h>
40 #include <fcntl.h>
41 #include <errno.h>
42 
43 
44 /* fwd */
45 static bool rewriteDex(u1* addr, int len, u4* pHeaderFlags,
46     DexClassLookup** ppClassLookup);
47 static bool loadAllClasses(DvmDex* pDvmDex);
48 static void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify,
49     bool doOpt);
50 static void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz,
51     const DexClassDef* pClassDef, bool doVerify, bool doOpt);
52 static void updateChecksum(u1* addr, int len, DexHeader* pHeader);
53 static int writeDependencies(int fd, u4 modWhen, u4 crc);
54 static bool writeOptData(int fd, const DexClassLookup* pClassLookup,\
55     const RegisterMapBuilder* pRegMapBuilder);
56 static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum);
57 
58 
59 /*
60  * Return the fd of an open file in the DEX file cache area.  If the cache
61  * file doesn't exist or is out of date, this will remove the old entry,
62  * create a new one (writing only the file header), and return with the
63  * "new file" flag set.
64  *
65  * It's possible to execute from an unoptimized DEX file directly,
66  * assuming the byte ordering and structure alignment is correct, but
67  * disadvantageous because some significant optimizations are not possible.
68  * It's not generally possible to do the same from an uncompressed Jar
69  * file entry, because we have to guarantee 32-bit alignment in the
70  * memory-mapped file.
71  *
72  * For a Jar/APK file (a zip archive with "classes.dex" inside), "modWhen"
73  * and "crc32" come from the Zip directory entry.  For a stand-alone DEX
74  * file, it's the modification date of the file and the Adler32 from the
75  * DEX header (which immediately follows the magic).  If these don't
76  * match what's stored in the opt header, we reject the file immediately.
77  *
78  * On success, the file descriptor will be positioned just past the "opt"
79  * file header, and will be locked with flock.  "*pCachedName" will point
80  * to newly-allocated storage.
81  */
dvmOpenCachedDexFile(const char * fileName,const char * cacheFileName,u4 modWhen,u4 crc,bool isBootstrap,bool * pNewFile,bool createIfMissing)82 int dvmOpenCachedDexFile(const char* fileName, const char* cacheFileName,
83     u4 modWhen, u4 crc, bool isBootstrap, bool* pNewFile, bool createIfMissing)
84 {
85     int fd, cc;
86     struct stat fdStat, fileStat;
87     bool readOnly = false;
88 
89     *pNewFile = false;
90 
91 retry:
92     /*
93      * Try to open the cache file.  If we've been asked to,
94      * create it if it doesn't exist.
95      */
96     fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1;
97     if (fd < 0) {
98         fd = open(cacheFileName, O_RDONLY, 0);
99         if (fd < 0) {
100             if (createIfMissing) {
101                 LOGE("Can't open dex cache '%s': %s\n",
102                     cacheFileName, strerror(errno));
103             }
104             return fd;
105         }
106         readOnly = true;
107     }
108 
109     /*
110      * Grab an exclusive lock on the cache file.  If somebody else is
111      * working on it, we'll block here until they complete.  Because
112      * we're waiting on an external resource, we go into VMWAIT mode.
113      */
114     int oldStatus;
115     LOGV("DexOpt: locking cache file %s (fd=%d, boot=%d)\n",
116         cacheFileName, fd, isBootstrap);
117     oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
118     cc = flock(fd, LOCK_EX | LOCK_NB);
119     if (cc != 0) {
120         LOGD("DexOpt: sleeping on flock(%s)\n", cacheFileName);
121         cc = flock(fd, LOCK_EX);
122     }
123     dvmChangeStatus(NULL, oldStatus);
124     if (cc != 0) {
125         LOGE("Can't lock dex cache '%s': %d\n", cacheFileName, cc);
126         close(fd);
127         return -1;
128     }
129     LOGV("DexOpt:  locked cache file\n");
130 
131     /*
132      * Check to see if the fd we opened and locked matches the file in
133      * the filesystem.  If they don't, then somebody else unlinked ours
134      * and created a new file, and we need to use that one instead.  (If
135      * we caught them between the unlink and the create, we'll get an
136      * ENOENT from the file stat.)
137      */
138     cc = fstat(fd, &fdStat);
139     if (cc != 0) {
140         LOGE("Can't stat open file '%s'\n", cacheFileName);
141         LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName);
142         goto close_fail;
143     }
144     cc = stat(cacheFileName, &fileStat);
145     if (cc != 0 ||
146         fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino)
147     {
148         LOGD("DexOpt: our open cache file is stale; sleeping and retrying\n");
149         LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName);
150         flock(fd, LOCK_UN);
151         close(fd);
152         usleep(250 * 1000);     /* if something is hosed, don't peg machine */
153         goto retry;
154     }
155 
156     /*
157      * We have the correct file open and locked.  If the file size is zero,
158      * then it was just created by us, and we want to fill in some fields
159      * in the "opt" header and set "*pNewFile".  Otherwise, we want to
160      * verify that the fields in the header match our expectations, and
161      * reset the file if they don't.
162      */
163     if (fdStat.st_size == 0) {
164         if (readOnly) {
165             LOGW("DexOpt: file has zero length and isn't writable\n");
166             goto close_fail;
167         }
168         cc = dexOptCreateEmptyHeader(fd);
169         if (cc != 0)
170             goto close_fail;
171         *pNewFile = true;
172         LOGV("DexOpt: successfully initialized new cache file\n");
173     } else {
174         bool expectVerify, expectOpt;
175 
176         if (gDvm.classVerifyMode == VERIFY_MODE_NONE)
177             expectVerify = false;
178         else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE)
179             expectVerify = !isBootstrap;
180         else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/
181             expectVerify = true;
182 
183         if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE)
184             expectOpt = false;
185         else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
186             expectOpt = expectVerify;
187         else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/
188             expectOpt = true;
189 
190         LOGV("checking deps, expecting vfy=%d opt=%d\n",
191             expectVerify, expectOpt);
192 
193         if (!dvmCheckOptHeaderAndDependencies(fd, true, modWhen, crc,
194                 expectVerify, expectOpt))
195         {
196             if (readOnly) {
197                 /*
198                  * We could unlink and rewrite the file if we own it or
199                  * the "sticky" bit isn't set on the directory.  However,
200                  * we're not able to truncate it, which spoils things.  So,
201                  * give up now.
202                  */
203                 if (createIfMissing) {
204                     LOGW("Cached DEX '%s' (%s) is stale and not writable\n",
205                         fileName, cacheFileName);
206                 }
207                 goto close_fail;
208             }
209 
210             /*
211              * If we truncate the existing file before unlinking it, any
212              * process that has it mapped will fail when it tries to touch
213              * the pages.
214              *
215              * This is very important.  The zygote process will have the
216              * boot DEX files (core, framework, etc.) mapped early.  If
217              * (say) core.dex gets updated, and somebody launches an app
218              * that uses App.dex, then App.dex gets reoptimized because it's
219              * dependent upon the boot classes.  However, dexopt will be
220              * using the *new* core.dex to do the optimizations, while the
221              * app will actually be running against the *old* core.dex
222              * because it starts from zygote.
223              *
224              * Even without zygote, it's still possible for a class loader
225              * to pull in an APK that was optimized against an older set
226              * of DEX files.  We must ensure that everything fails when a
227              * boot DEX gets updated, and for general "why aren't my
228              * changes doing anything" purposes its best if we just make
229              * everything crash when a DEX they're using gets updated.
230              */
231             LOGD("ODEX file is stale or bad; removing and retrying (%s)\n",
232                 cacheFileName);
233             if (ftruncate(fd, 0) != 0) {
234                 LOGW("Warning: unable to truncate cache file '%s': %s\n",
235                     cacheFileName, strerror(errno));
236                 /* keep going */
237             }
238             if (unlink(cacheFileName) != 0) {
239                 LOGW("Warning: unable to remove cache file '%s': %d %s\n",
240                     cacheFileName, errno, strerror(errno));
241                 /* keep going; permission failure should probably be fatal */
242             }
243             LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName);
244             flock(fd, LOCK_UN);
245             close(fd);
246             goto retry;
247         } else {
248             LOGV("DexOpt: good deps in cache file\n");
249         }
250     }
251 
252     assert(fd >= 0);
253     return fd;
254 
255 close_fail:
256     flock(fd, LOCK_UN);
257     close(fd);
258     return -1;
259 }
260 
261 /*
262  * Unlock the file descriptor.
263  *
264  * Returns "true" on success.
265  */
dvmUnlockCachedDexFile(int fd)266 bool dvmUnlockCachedDexFile(int fd)
267 {
268     LOGVV("DexOpt: unlocking cache file fd=%d\n", fd);
269     return (flock(fd, LOCK_UN) == 0);
270 }
271 
272 
273 /*
274  * Given a descriptor for a file with DEX data in it, produce an
275  * optimized version.
276  *
277  * The file pointed to by "fd" is expected to be a locked shared resource
278  * (or private); we make no efforts to enforce multi-process correctness
279  * here.
280  *
281  * "fileName" is only used for debug output.  "modWhen" and "crc" are stored
282  * in the dependency set.
283  *
284  * The "isBootstrap" flag determines how the optimizer and verifier handle
285  * package-scope access checks.  When optimizing, we only load the bootstrap
286  * class DEX files and the target DEX, so the flag determines whether the
287  * target DEX classes are given a (synthetic) non-NULL classLoader pointer.
288  * This only really matters if the target DEX contains classes that claim to
289  * be in the same package as bootstrap classes.
290  *
291  * The optimizer will need to load every class in the target DEX file.
292  * This is generally undesirable, so we start a subprocess to do the
293  * work and wait for it to complete.
294  *
295  * Returns "true" on success.  All data will have been written to "fd".
296  */
dvmOptimizeDexFile(int fd,off_t dexOffset,long dexLength,const char * fileName,u4 modWhen,u4 crc,bool isBootstrap)297 bool dvmOptimizeDexFile(int fd, off_t dexOffset, long dexLength,
298     const char* fileName, u4 modWhen, u4 crc, bool isBootstrap)
299 {
300     const char* lastPart = strrchr(fileName, '/');
301     if (lastPart != NULL)
302         lastPart++;
303     else
304         lastPart = fileName;
305 
306     LOGD("DexOpt: --- BEGIN '%s' (bootstrap=%d) ---\n", lastPart, isBootstrap);
307 
308     pid_t pid;
309 
310     /*
311      * This could happen if something in our bootclasspath, which we thought
312      * was all optimized, got rejected.
313      */
314     if (gDvm.optimizing) {
315         LOGW("Rejecting recursive optimization attempt on '%s'\n", fileName);
316         return false;
317     }
318 
319     pid = fork();
320     if (pid == 0) {
321         static const int kUseValgrind = 0;
322         static const char* kDexOptBin = "/bin/dexopt";
323         static const char* kValgrinder = "/usr/bin/valgrind";
324         static const int kFixedArgCount = 10;
325         static const int kValgrindArgCount = 5;
326         static const int kMaxIntLen = 12;   // '-'+10dig+'\0' -OR- 0x+8dig
327         int bcpSize = dvmGetBootPathSize();
328         int argc = kFixedArgCount + bcpSize
329             + (kValgrindArgCount * kUseValgrind);
330         char* argv[argc+1];             // last entry is NULL
331         char values[argc][kMaxIntLen];
332         char* execFile;
333         char* androidRoot;
334         int flags;
335 
336         /* change process groups, so we don't clash with ProcessManager */
337         setpgid(0, 0);
338 
339         /* full path to optimizer */
340         androidRoot = getenv("ANDROID_ROOT");
341         if (androidRoot == NULL) {
342             LOGW("ANDROID_ROOT not set, defaulting to /system\n");
343             androidRoot = "/system";
344         }
345         execFile = malloc(strlen(androidRoot) + strlen(kDexOptBin) + 1);
346         strcpy(execFile, androidRoot);
347         strcat(execFile, kDexOptBin);
348 
349         /*
350          * Create arg vector.
351          */
352         int curArg = 0;
353 
354         if (kUseValgrind) {
355             /* probably shouldn't ship the hard-coded path */
356             argv[curArg++] = (char*)kValgrinder;
357             argv[curArg++] = "--tool=memcheck";
358             argv[curArg++] = "--leak-check=yes";        // check for leaks too
359             argv[curArg++] = "--leak-resolution=med";   // increase from 2 to 4
360             argv[curArg++] = "--num-callers=16";        // default is 12
361             assert(curArg == kValgrindArgCount);
362         }
363         argv[curArg++] = execFile;
364 
365         argv[curArg++] = "--dex";
366 
367         sprintf(values[2], "%d", DALVIK_VM_BUILD);
368         argv[curArg++] = values[2];
369 
370         sprintf(values[3], "%d", fd);
371         argv[curArg++] = values[3];
372 
373         sprintf(values[4], "%d", (int) dexOffset);
374         argv[curArg++] = values[4];
375 
376         sprintf(values[5], "%d", (int) dexLength);
377         argv[curArg++] = values[5];
378 
379         argv[curArg++] = (char*)fileName;
380 
381         sprintf(values[7], "%d", (int) modWhen);
382         argv[curArg++] = values[7];
383 
384         sprintf(values[8], "%d", (int) crc);
385         argv[curArg++] = values[8];
386 
387         flags = 0;
388         if (gDvm.dexOptMode != OPTIMIZE_MODE_NONE) {
389             flags |= DEXOPT_OPT_ENABLED;
390             if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)
391                 flags |= DEXOPT_OPT_ALL;
392         }
393         if (gDvm.classVerifyMode != VERIFY_MODE_NONE) {
394             flags |= DEXOPT_VERIFY_ENABLED;
395             if (gDvm.classVerifyMode == VERIFY_MODE_ALL)
396                 flags |= DEXOPT_VERIFY_ALL;
397         }
398         if (isBootstrap)
399             flags |= DEXOPT_IS_BOOTSTRAP;
400         if (gDvm.generateRegisterMaps)
401             flags |= DEXOPT_GEN_REGISTER_MAPS;
402         sprintf(values[9], "%d", flags);
403         argv[curArg++] = values[9];
404 
405         assert(((!kUseValgrind && curArg == kFixedArgCount) ||
406                ((kUseValgrind && curArg == kFixedArgCount+kValgrindArgCount))));
407 
408         ClassPathEntry* cpe;
409         for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
410             argv[curArg++] = cpe->fileName;
411         }
412         assert(curArg == argc);
413 
414         argv[curArg] = NULL;
415 
416         if (kUseValgrind)
417             execv(kValgrinder, argv);
418         else
419             execv(execFile, argv);
420 
421         LOGE("execv '%s'%s failed: %s\n", execFile,
422             kUseValgrind ? " [valgrind]" : "", strerror(errno));
423         exit(1);
424     } else {
425         LOGV("DexOpt: waiting for verify+opt, pid=%d\n", (int) pid);
426         int status;
427         pid_t gotPid;
428         int oldStatus;
429 
430         /*
431          * Wait for the optimization process to finish.  We go into VMWAIT
432          * mode here so GC suspension won't have to wait for us.
433          */
434         oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
435         while (true) {
436             gotPid = waitpid(pid, &status, 0);
437             if (gotPid == -1 && errno == EINTR) {
438                 LOGD("waitpid interrupted, retrying\n");
439             } else {
440                 break;
441             }
442         }
443         dvmChangeStatus(NULL, oldStatus);
444         if (gotPid != pid) {
445             LOGE("waitpid failed: wanted %d, got %d: %s\n",
446                 (int) pid, (int) gotPid, strerror(errno));
447             return false;
448         }
449 
450         if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
451             LOGD("DexOpt: --- END '%s' (success) ---\n", lastPart);
452             return true;
453         } else {
454             LOGW("DexOpt: --- END '%s' --- status=0x%04x, process failed\n",
455                 lastPart, status);
456             return false;
457         }
458     }
459 }
460 
461 /*
462  * Do the actual optimization.  This is executed in the dexopt process.
463  *
464  * For best use of disk/memory, we want to extract once and perform
465  * optimizations in place.  If the file has to expand or contract
466  * to match local structure padding/alignment expectations, we want
467  * to do the rewrite as part of the extract, rather than extracting
468  * into a temp file and slurping it back out.  (The structure alignment
469  * is currently correct for all platforms, and this isn't expected to
470  * change, so we should be okay with having it already extracted.)
471  *
472  * Returns "true" on success.
473  */
dvmContinueOptimization(int fd,off_t dexOffset,long dexLength,const char * fileName,u4 modWhen,u4 crc,bool isBootstrap)474 bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength,
475     const char* fileName, u4 modWhen, u4 crc, bool isBootstrap)
476 {
477     DexClassLookup* pClassLookup = NULL;
478     RegisterMapBuilder* pRegMapBuilder = NULL;
479     u4 headerFlags = 0;
480 
481     assert(gDvm.optimizing);
482 
483     LOGV("Continuing optimization (%s, isb=%d, vfy=%d, opt=%d)\n",
484         fileName, isBootstrap, doVerify, doOpt);
485 
486     assert(dexOffset >= 0);
487 
488     /* quick test so we don't blow up on empty file */
489     if (dexLength < (int) sizeof(DexHeader)) {
490         LOGE("too small to be DEX\n");
491         return false;
492     }
493     if (dexOffset < (int) sizeof(DexOptHeader)) {
494         LOGE("not enough room for opt header\n");
495         return false;
496     }
497 
498     bool result = false;
499 
500     /*
501      * Drop this into a global so we don't have to pass it around.  We could
502      * also add a field to DexFile, but since it only pertains to DEX
503      * creation that probably doesn't make sense.
504      */
505     gDvm.optimizingBootstrapClass = isBootstrap;
506 
507     {
508         /*
509          * Map the entire file (so we don't have to worry about page
510          * alignment).  The expectation is that the output file contains
511          * our DEX data plus room for a small header.
512          */
513         bool success;
514         void* mapAddr;
515         mapAddr = mmap(NULL, dexOffset + dexLength, PROT_READ|PROT_WRITE,
516                     MAP_SHARED, fd, 0);
517         if (mapAddr == MAP_FAILED) {
518             LOGE("unable to mmap DEX cache: %s\n", strerror(errno));
519             goto bail;
520         }
521 
522         /*
523          * Rewrite the file.  Byte reordering, structure realigning,
524          * class verification, and bytecode optimization are all performed
525          * here.
526          *
527          * In theory the file could change size and bits could shift around.
528          * In practice this would be annoying to deal with, so the file
529          * layout is designed so that it can always be rewritten in place.
530          *
531          * This sets "headerFlags" and creates the class lookup table as
532          * part of doing the processing.
533          */
534         success = rewriteDex(((u1*) mapAddr) + dexOffset, dexLength,
535                     &headerFlags, &pClassLookup);
536 
537         if (success) {
538             DvmDex* pDvmDex = NULL;
539             u1* dexAddr = ((u1*) mapAddr) + dexOffset;
540 
541             if (dvmDexFileOpenPartial(dexAddr, dexLength, &pDvmDex) != 0) {
542                 LOGE("Unable to create DexFile\n");
543                 success = false;
544             } else {
545                 /*
546                  * If configured to do so, generate register map output
547                  * for all verified classes.  The register maps were
548                  * generated during verification, and will now be serialized.
549                  */
550                 if (gDvm.generateRegisterMaps) {
551                     pRegMapBuilder = dvmGenerateRegisterMaps(pDvmDex);
552                     if (pRegMapBuilder == NULL) {
553                         LOGE("Failed generating register maps\n");
554                         success = false;
555                     }
556                 }
557 
558                 DexHeader* pHeader = (DexHeader*)pDvmDex->pHeader;
559                 updateChecksum(dexAddr, dexLength, pHeader);
560 
561                 dvmDexFileFree(pDvmDex);
562             }
563         }
564 
565         /* unmap the read-write version, forcing writes to disk */
566         if (msync(mapAddr, dexOffset + dexLength, MS_SYNC) != 0) {
567             LOGW("msync failed: %s\n", strerror(errno));
568             // weird, but keep going
569         }
570 #if 1
571         /*
572          * This causes clean shutdown to fail, because we have loaded classes
573          * that point into it.  For the optimizer this isn't a problem,
574          * because it's more efficient for the process to simply exit.
575          * Exclude this code when doing clean shutdown for valgrind.
576          */
577         if (munmap(mapAddr, dexOffset + dexLength) != 0) {
578             LOGE("munmap failed: %s\n", strerror(errno));
579             goto bail;
580         }
581 #endif
582 
583         if (!success)
584             goto bail;
585     }
586 
587     /* get start offset, and adjust deps start for 64-bit alignment */
588     off_t depsOffset, optOffset, endOffset, adjOffset;
589     int depsLength, optLength;
590     u4 optChecksum;
591 
592     depsOffset = lseek(fd, 0, SEEK_END);
593     if (depsOffset < 0) {
594         LOGE("lseek to EOF failed: %s\n", strerror(errno));
595         goto bail;
596     }
597     adjOffset = (depsOffset + 7) & ~(0x07);
598     if (adjOffset != depsOffset) {
599         LOGV("Adjusting deps start from %d to %d\n",
600             (int) depsOffset, (int) adjOffset);
601         depsOffset = adjOffset;
602         lseek(fd, depsOffset, SEEK_SET);
603     }
604 
605     /*
606      * Append the dependency list.
607      */
608     if (writeDependencies(fd, modWhen, crc) != 0) {
609         LOGW("Failed writing dependencies\n");
610         goto bail;
611     }
612 
613     /* compute deps length, then adjust opt start for 64-bit alignment */
614     optOffset = lseek(fd, 0, SEEK_END);
615     depsLength = optOffset - depsOffset;
616 
617     adjOffset = (optOffset + 7) & ~(0x07);
618     if (adjOffset != optOffset) {
619         LOGV("Adjusting opt start from %d to %d\n",
620             (int) optOffset, (int) adjOffset);
621         optOffset = adjOffset;
622         lseek(fd, optOffset, SEEK_SET);
623     }
624 
625     /*
626      * Append any optimized pre-computed data structures.
627      */
628     if (!writeOptData(fd, pClassLookup, pRegMapBuilder)) {
629         LOGW("Failed writing opt data\n");
630         goto bail;
631     }
632 
633     endOffset = lseek(fd, 0, SEEK_END);
634     optLength = endOffset - optOffset;
635 
636     /* compute checksum from start of deps to end of opt area */
637     if (!computeFileChecksum(fd, depsOffset,
638             (optOffset+optLength) - depsOffset, &optChecksum))
639     {
640         goto bail;
641     }
642 
643     /*
644      * Output the "opt" header with all values filled in and a correct
645      * magic number.
646      */
647     DexOptHeader optHdr;
648     memset(&optHdr, 0xff, sizeof(optHdr));
649     memcpy(optHdr.magic, DEX_OPT_MAGIC, 4);
650     memcpy(optHdr.magic+4, DEX_OPT_MAGIC_VERS, 4);
651     optHdr.dexOffset = (u4) dexOffset;
652     optHdr.dexLength = (u4) dexLength;
653     optHdr.depsOffset = (u4) depsOffset;
654     optHdr.depsLength = (u4) depsLength;
655     optHdr.optOffset = (u4) optOffset;
656     optHdr.optLength = (u4) optLength;
657 
658     optHdr.flags = headerFlags;
659     optHdr.checksum = optChecksum;
660 
661     fsync(fd);      /* ensure previous writes go before header is written */
662 
663     lseek(fd, 0, SEEK_SET);
664     if (sysWriteFully(fd, &optHdr, sizeof(optHdr), "DexOpt opt header") != 0)
665         goto bail;
666 
667     LOGV("Successfully wrote DEX header\n");
668     result = true;
669 
670     //dvmRegisterMapDumpStats();
671 
672 bail:
673     dvmFreeRegisterMapBuilder(pRegMapBuilder);
674     free(pClassLookup);
675     return result;
676 }
677 
678 
679 /*
680  * Perform in-place rewrites on a memory-mapped DEX file.
681  *
682  * This happens in a short-lived child process, so we can go nutty with
683  * loading classes and allocating memory.
684  */
rewriteDex(u1 * addr,int len,u4 * pHeaderFlags,DexClassLookup ** ppClassLookup)685 static bool rewriteDex(u1* addr, int len, u4* pHeaderFlags,
686     DexClassLookup** ppClassLookup)
687 {
688     u8 prepWhen, loadWhen, verifyOptWhen;
689     DvmDex* pDvmDex = NULL;
690     bool doVerify, doOpt;
691     bool result = false;
692 
693     *pHeaderFlags = 0;
694 
695     /* if the DEX is in the wrong byte order, swap it now */
696     if (dexSwapAndVerify(addr, len) != 0)
697         goto bail;
698 #if __BYTE_ORDER != __LITTLE_ENDIAN
699     *pHeaderFlags |= DEX_OPT_FLAG_BIG;
700 #endif
701 
702     if (gDvm.classVerifyMode == VERIFY_MODE_NONE)
703         doVerify = false;
704     else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE)
705         doVerify = !gDvm.optimizingBootstrapClass;
706     else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/
707         doVerify = true;
708 
709     if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE)
710         doOpt = false;
711     else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)
712         doOpt = doVerify;
713     else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/
714         doOpt = true;
715 
716     /* TODO: decide if this is actually useful */
717     if (doVerify)
718         *pHeaderFlags |= DEX_FLAG_VERIFIED;
719     if (doOpt)
720         *pHeaderFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS;
721 
722     /*
723      * Now that the DEX file can be read directly, create a DexFile struct
724      * for it.
725      */
726     if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) {
727         LOGE("Unable to create DexFile\n");
728         goto bail;
729     }
730 
731     /*
732      * Create the class lookup table.  This will eventually be appended
733      * to the end of the .odex.
734      */
735     *ppClassLookup = dexCreateClassLookup(pDvmDex->pDexFile);
736     if (*ppClassLookup == NULL)
737         goto bail;
738 
739     /*
740      * If we're not going to attempt to verify or optimize the classes,
741      * there's no value in loading them, so bail out early.
742      */
743     if (!doVerify && !doOpt) {
744         result = true;
745         goto bail;
746     }
747 
748     /* this is needed for the next part */
749     pDvmDex->pDexFile->pClassLookup = *ppClassLookup;
750 
751     prepWhen = dvmGetRelativeTimeUsec();
752 
753     /*
754      * Load all classes found in this DEX file.  If they fail to load for
755      * some reason, they won't get verified (which is as it should be).
756      */
757     if (!loadAllClasses(pDvmDex))
758         goto bail;
759     loadWhen = dvmGetRelativeTimeUsec();
760 
761     /*
762      * Verify and optimize all classes in the DEX file (command-line
763      * options permitting).
764      *
765      * This is best-effort, so there's really no way for dexopt to
766      * fail at this point.
767      */
768     verifyAndOptimizeClasses(pDvmDex->pDexFile, doVerify, doOpt);
769     verifyOptWhen = dvmGetRelativeTimeUsec();
770 
771     const char* msgStr = "???";
772     if (doVerify && doOpt)
773         msgStr = "verify+opt";
774     else if (doVerify)
775         msgStr = "verify";
776     else if (doOpt)
777         msgStr = "opt";
778     LOGD("DexOpt: load %dms, %s %dms\n",
779         (int) (loadWhen - prepWhen) / 1000,
780         msgStr,
781         (int) (verifyOptWhen - loadWhen) / 1000);
782 
783     result = true;
784 
785 bail:
786     /* free up storage */
787     dvmDexFileFree(pDvmDex);
788 
789     return result;
790 }
791 
792 /*
793  * Try to load all classes in the specified DEX.  If they have some sort
794  * of broken dependency, e.g. their superclass lives in a different DEX
795  * that wasn't previously loaded into the bootstrap class path, loading
796  * will fail.  This is the desired behavior.
797  *
798  * We have no notion of class loader at this point, so we load all of
799  * the classes with the bootstrap class loader.  It turns out this has
800  * exactly the behavior we want, and has no ill side effects because we're
801  * running in a separate process and anything we load here will be forgotten.
802  *
803  * We set the CLASS_MULTIPLE_DEFS flag here if we see multiple definitions.
804  * This works because we only call here as part of optimization / pre-verify,
805  * not during verification as part of loading a class into a running VM.
806  *
807  * This returns "false" if the world is too screwed up to do anything
808  * useful at all.
809  */
loadAllClasses(DvmDex * pDvmDex)810 static bool loadAllClasses(DvmDex* pDvmDex)
811 {
812     u4 count = pDvmDex->pDexFile->pHeader->classDefsSize;
813     u4 idx;
814     int loaded = 0;
815 
816     LOGV("DexOpt: +++ trying to load %d classes\n", count);
817 
818     dvmSetBootPathExtraDex(pDvmDex);
819 
820     /*
821      * We have some circularity issues with Class and Object that are most
822      * easily avoided by ensuring that Object is never the first thing we
823      * try to find.  Take care of that here.  (We only need to do this when
824      * loading classes from the DEX file that contains Object, and only
825      * when Object comes first in the list, but it costs very little to
826      * do it in all cases.)
827      */
828     if (dvmFindSystemClass("Ljava/lang/Class;") == NULL) {
829         LOGE("ERROR: java.lang.Class does not exist!\n");
830         return false;
831     }
832 
833     for (idx = 0; idx < count; idx++) {
834         const DexClassDef* pClassDef;
835         const char* classDescriptor;
836         ClassObject* newClass;
837 
838         pClassDef = dexGetClassDef(pDvmDex->pDexFile, idx);
839         classDescriptor =
840             dexStringByTypeIdx(pDvmDex->pDexFile, pClassDef->classIdx);
841 
842         LOGV("+++  loading '%s'", classDescriptor);
843         //newClass = dvmDefineClass(pDexFile, classDescriptor,
844         //        NULL);
845         newClass = dvmFindSystemClassNoInit(classDescriptor);
846         if (newClass == NULL) {
847             LOGV("DexOpt: failed loading '%s'\n", classDescriptor);
848             dvmClearOptException(dvmThreadSelf());
849         } else if (newClass->pDvmDex != pDvmDex) {
850             /*
851              * We don't load the new one, and we tag the first one found
852              * with the "multiple def" flag so the resolver doesn't try
853              * to make it available.
854              */
855             LOGD("DexOpt: '%s' has an earlier definition; blocking out\n",
856                 classDescriptor);
857             SET_CLASS_FLAG(newClass, CLASS_MULTIPLE_DEFS);
858         } else {
859             loaded++;
860         }
861     }
862     LOGV("DexOpt: +++ successfully loaded %d classes\n", loaded);
863 
864     dvmSetBootPathExtraDex(NULL);
865     return true;
866 }
867 
868 /*
869  * Verify and/or optimize all classes that were successfully loaded from
870  * this DEX file.
871  */
verifyAndOptimizeClasses(DexFile * pDexFile,bool doVerify,bool doOpt)872 static void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify,
873     bool doOpt)
874 {
875     u4 count = pDexFile->pHeader->classDefsSize;
876     u4 idx;
877 
878     /*
879      * Create a data structure for use by the bytecode optimizer.  We
880      * stuff it into a global so we don't have to pass it around as
881      * a function argument.
882      *
883      * We could create this at VM startup, but there's no need to do so
884      * unless we're optimizing, which means we're in dexopt, and we're
885      * only going to call here once.
886      */
887     if (doOpt) {
888         gDvm.inlineSubs = dvmCreateInlineSubsTable();
889         if (gDvm.inlineSubs == NULL)
890             return;
891     }
892 
893     for (idx = 0; idx < count; idx++) {
894         const DexClassDef* pClassDef;
895         const char* classDescriptor;
896         ClassObject* clazz;
897 
898         pClassDef = dexGetClassDef(pDexFile, idx);
899         classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
900 
901         /* all classes are loaded into the bootstrap class loader */
902         clazz = dvmLookupClass(classDescriptor, NULL, false);
903         if (clazz != NULL) {
904             verifyAndOptimizeClass(pDexFile, clazz, pClassDef, doVerify, doOpt);
905 
906         } else {
907             // TODO: log when in verbose mode
908             LOGV("DexOpt: not optimizing unavailable class '%s'\n",
909                 classDescriptor);
910         }
911     }
912 
913     if (gDvm.inlineSubs != NULL) {
914         dvmFreeInlineSubsTable(gDvm.inlineSubs);
915         gDvm.inlineSubs = NULL;
916     }
917 }
918 
919 /*
920  * Verify and/or optimize a specific class.
921  */
verifyAndOptimizeClass(DexFile * pDexFile,ClassObject * clazz,const DexClassDef * pClassDef,bool doVerify,bool doOpt)922 static void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz,
923     const DexClassDef* pClassDef, bool doVerify, bool doOpt)
924 {
925     const char* classDescriptor;
926     bool verified = false;
927 
928     classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
929 
930     /*
931      * First, try to verify it.
932      */
933     if (doVerify) {
934         if (clazz->pDvmDex->pDexFile != pDexFile) {
935             LOGD("DexOpt: not verifying '%s': multiple definitions\n",
936                 classDescriptor);
937         } else {
938             if (dvmVerifyClass(clazz)) {
939                 /*
940                  * Set the "is preverified" flag in the DexClassDef.  We
941                  * do it here, rather than in the ClassObject structure,
942                  * because the DexClassDef is part of the odex file.
943                  */
944                 assert((clazz->accessFlags & JAVA_FLAGS_MASK) ==
945                     pClassDef->accessFlags);
946                 ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISPREVERIFIED;
947                 verified = true;
948             } else {
949                 // TODO: log when in verbose mode
950                 LOGV("DexOpt: '%s' failed verification\n", classDescriptor);
951             }
952         }
953     }
954 
955     if (doOpt) {
956         if (!verified && gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED) {
957             LOGV("DexOpt: not optimizing '%s': not verified\n",
958                 classDescriptor);
959         } else {
960             dvmOptimizeClass(clazz, false);
961 
962             /* set the flag whether or not we actually changed anything */
963             ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISOPTIMIZED;
964         }
965     }
966 }
967 
968 
969 /*
970  * Get the cache file name from a ClassPathEntry.
971  */
getCacheFileName(const ClassPathEntry * cpe)972 static const char* getCacheFileName(const ClassPathEntry* cpe)
973 {
974     switch (cpe->kind) {
975     case kCpeJar:
976         return dvmGetJarFileCacheFileName((JarFile*) cpe->ptr);
977     case kCpeDex:
978         return dvmGetRawDexFileCacheFileName((RawDexFile*) cpe->ptr);
979     default:
980         LOGE("DexOpt: unexpected cpe kind %d\n", cpe->kind);
981         dvmAbort();
982         return NULL;
983     }
984 }
985 
986 /*
987  * Get the SHA-1 signature.
988  */
getSignature(const ClassPathEntry * cpe)989 static const u1* getSignature(const ClassPathEntry* cpe)
990 {
991     DvmDex* pDvmDex;
992 
993     switch (cpe->kind) {
994     case kCpeJar:
995         pDvmDex = dvmGetJarFileDex((JarFile*) cpe->ptr);
996         break;
997     case kCpeDex:
998         pDvmDex = dvmGetRawDexFileDex((RawDexFile*) cpe->ptr);
999         break;
1000     default:
1001         LOGE("unexpected cpe kind %d\n", cpe->kind);
1002         dvmAbort();
1003         pDvmDex = NULL;         // make gcc happy
1004     }
1005 
1006     assert(pDvmDex != NULL);
1007     return pDvmDex->pDexFile->pHeader->signature;
1008 }
1009 
1010 
1011 /*
1012  * Dependency layout:
1013  *  4b  Source file modification time, in seconds since 1970 UTC
1014  *  4b  CRC-32 from Zip entry, or Adler32 from source DEX header
1015  *  4b  Dalvik VM build number
1016  *  4b  Number of dependency entries that follow
1017  *  Dependency entries:
1018  *    4b  Name length (including terminating null)
1019  *    var Full path of cache entry (null terminated)
1020  *    20b SHA-1 signature from source DEX file
1021  *
1022  * If this changes, update DEX_OPT_MAGIC_VERS.
1023  */
1024 static const size_t kMinDepSize = 4 * 4;
1025 static const size_t kMaxDepSize = 4 * 4 + 2048;     // sanity check
1026 
1027 /*
1028  * Read the "opt" header, verify it, then read the dependencies section
1029  * and verify that data as well.
1030  *
1031  * If "sourceAvail" is "true", this will verify that "modWhen" and "crc"
1032  * match up with what is stored in the header.  If they don't, we reject
1033  * the file so that it can be recreated from the updated original.  If
1034  * "sourceAvail" isn't set, e.g. for a .odex file, we ignore these arguments.
1035  *
1036  * On successful return, the file will be seeked immediately past the
1037  * "opt" header.
1038  */
dvmCheckOptHeaderAndDependencies(int fd,bool sourceAvail,u4 modWhen,u4 crc,bool expectVerify,bool expectOpt)1039 bool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen,
1040     u4 crc, bool expectVerify, bool expectOpt)
1041 {
1042     DexOptHeader optHdr;
1043     u1* depData = NULL;
1044     const u1* magic;
1045     off_t posn;
1046     int result = false;
1047     ssize_t actual;
1048 
1049     /*
1050      * Start at the start.  The "opt" header, when present, will always be
1051      * the first thing in the file.
1052      */
1053     if (lseek(fd, 0, SEEK_SET) != 0) {
1054         LOGE("DexOpt: failed to seek to start of file: %s\n", strerror(errno));
1055         goto bail;
1056     }
1057 
1058     /*
1059      * Read and do trivial verification on the opt header.  The header is
1060      * always in host byte order.
1061      */
1062     actual = read(fd, &optHdr, sizeof(optHdr));
1063     if (actual < 0) {
1064         LOGE("DexOpt: failed reading opt header: %s\n", strerror(errno));
1065         goto bail;
1066     } else if (actual != sizeof(optHdr)) {
1067         LOGE("DexOpt: failed reading opt header (got %d of %zd)\n",
1068             (int) actual, sizeof(optHdr));
1069         goto bail;
1070     }
1071 
1072     magic = optHdr.magic;
1073     if (memcmp(magic, DEX_MAGIC, 4) == 0) {
1074         /* somebody probably pointed us at the wrong file */
1075         LOGD("DexOpt: expected optimized DEX, found unoptimized\n");
1076         goto bail;
1077     } else if (memcmp(magic, DEX_OPT_MAGIC, 4) != 0) {
1078         /* not a DEX file, or previous attempt was interrupted */
1079         LOGD("DexOpt: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
1080             magic[0], magic[1], magic[2], magic[3]);
1081         goto bail;
1082     }
1083     if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) {
1084         LOGW("DexOpt: stale opt version (0x%02x %02x %02x %02x)\n",
1085             magic[4], magic[5], magic[6], magic[7]);
1086         goto bail;
1087     }
1088     if (optHdr.depsLength < kMinDepSize || optHdr.depsLength > kMaxDepSize) {
1089         LOGW("DexOpt: weird deps length %d, bailing\n", optHdr.depsLength);
1090         goto bail;
1091     }
1092 
1093     /*
1094      * Do the header flags match up with what we want?
1095      *
1096      * This is useful because it allows us to automatically regenerate
1097      * a file when settings change (e.g. verification is now mandatory),
1098      * but can cause difficulties if the bootstrap classes we depend upon
1099      * were handled differently than the current options specify.  We get
1100      * upset because they're not verified or optimized, but we're not able
1101      * to regenerate them because the installer won't let us.
1102      *
1103      * (This is also of limited value when !sourceAvail.)
1104      *
1105      * So, for now, we essentially ignore "expectVerify" and "expectOpt"
1106      * by limiting the match mask.
1107      *
1108      * The only thing we really can't handle is incorrect byte-ordering.
1109      */
1110     const u4 matchMask = DEX_OPT_FLAG_BIG;
1111     u4 expectedFlags = 0;
1112 #if __BYTE_ORDER != __LITTLE_ENDIAN
1113     expectedFlags |= DEX_OPT_FLAG_BIG;
1114 #endif
1115     if (expectVerify)
1116         expectedFlags |= DEX_FLAG_VERIFIED;
1117     if (expectOpt)
1118         expectedFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS;
1119     if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) {
1120         LOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)\n",
1121             expectedFlags, optHdr.flags, matchMask);
1122         goto bail;
1123     }
1124 
1125     posn = lseek(fd, optHdr.depsOffset, SEEK_SET);
1126     if (posn < 0) {
1127         LOGW("DexOpt: seek to deps failed: %s\n", strerror(errno));
1128         goto bail;
1129     }
1130 
1131     /*
1132      * Read all of the dependency stuff into memory.
1133      */
1134     depData = (u1*) malloc(optHdr.depsLength);
1135     if (depData == NULL) {
1136         LOGW("DexOpt: unable to allocate %d bytes for deps\n",
1137             optHdr.depsLength);
1138         goto bail;
1139     }
1140     actual = read(fd, depData, optHdr.depsLength);
1141     if (actual < 0) {
1142         LOGW("DexOpt: failed reading deps: %s\n", strerror(errno));
1143         goto bail;
1144     } else if (actual != (ssize_t) optHdr.depsLength) {
1145         LOGW("DexOpt: failed reading deps: got %d of %d\n",
1146             (int) actual, optHdr.depsLength);
1147         goto bail;
1148     }
1149 
1150     /*
1151      * Verify simple items.
1152      */
1153     const u1* ptr;
1154     u4 val;
1155 
1156     ptr = depData;
1157     val = read4LE(&ptr);
1158     if (sourceAvail && val != modWhen) {
1159         LOGI("DexOpt: source file mod time mismatch (%08x vs %08x)\n",
1160             val, modWhen);
1161         goto bail;
1162     }
1163     val = read4LE(&ptr);
1164     if (sourceAvail && val != crc) {
1165         LOGI("DexOpt: source file CRC mismatch (%08x vs %08x)\n", val, crc);
1166         goto bail;
1167     }
1168     val = read4LE(&ptr);
1169     if (val != DALVIK_VM_BUILD) {
1170         LOGD("DexOpt: VM build version mismatch (%d vs %d)\n",
1171             val, DALVIK_VM_BUILD);
1172         goto bail;
1173     }
1174 
1175     /*
1176      * Verify dependencies on other cached DEX files.  It must match
1177      * exactly with what is currently defined in the bootclasspath.
1178      */
1179     ClassPathEntry* cpe;
1180     u4 numDeps;
1181 
1182     numDeps = read4LE(&ptr);
1183     LOGV("+++ DexOpt: numDeps = %d\n", numDeps);
1184     for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
1185         const char* cacheFileName =
1186             dvmPathToAbsolutePortion(getCacheFileName(cpe));
1187         assert(cacheFileName != NULL); /* guaranteed by Class.c */
1188 
1189         const u1* signature = getSignature(cpe);
1190         size_t len = strlen(cacheFileName) +1;
1191         u4 storedStrLen;
1192 
1193         if (numDeps == 0) {
1194             /* more entries in bootclasspath than in deps list */
1195             LOGI("DexOpt: not all deps represented\n");
1196             goto bail;
1197         }
1198 
1199         storedStrLen = read4LE(&ptr);
1200         if (len != storedStrLen ||
1201             strcmp(cacheFileName, (const char*) ptr) != 0)
1202         {
1203             LOGI("DexOpt: mismatch dep name: '%s' vs. '%s'\n",
1204                 cacheFileName, ptr);
1205             goto bail;
1206         }
1207 
1208         ptr += storedStrLen;
1209 
1210         if (memcmp(signature, ptr, kSHA1DigestLen) != 0) {
1211             LOGI("DexOpt: mismatch dep signature for '%s'\n", cacheFileName);
1212             goto bail;
1213         }
1214         ptr += kSHA1DigestLen;
1215 
1216         LOGV("DexOpt: dep match on '%s'\n", cacheFileName);
1217 
1218         numDeps--;
1219     }
1220 
1221     if (numDeps != 0) {
1222         /* more entries in deps list than in classpath */
1223         LOGI("DexOpt: Some deps went away\n");
1224         goto bail;
1225     }
1226 
1227     // consumed all data and no more?
1228     if (ptr != depData + optHdr.depsLength) {
1229         LOGW("DexOpt: Spurious dep data? %d vs %d\n",
1230             (int) (ptr - depData), optHdr.depsLength);
1231         assert(false);
1232     }
1233 
1234     result = true;
1235 
1236 bail:
1237     free(depData);
1238     return result;
1239 }
1240 
1241 /*
1242  * Write the dependency info to "fd" at the current file position.
1243  */
writeDependencies(int fd,u4 modWhen,u4 crc)1244 static int writeDependencies(int fd, u4 modWhen, u4 crc)
1245 {
1246     u1* buf = NULL;
1247     int result = -1;
1248     ssize_t bufLen;
1249     ClassPathEntry* cpe;
1250     int numDeps;
1251 
1252     /*
1253      * Count up the number of completed entries in the bootclasspath.
1254      */
1255     numDeps = 0;
1256     bufLen = 0;
1257     for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
1258         const char* cacheFileName =
1259             dvmPathToAbsolutePortion(getCacheFileName(cpe));
1260         assert(cacheFileName != NULL); /* guaranteed by Class.c */
1261 
1262         LOGV("+++ DexOpt: found dep '%s'\n", cacheFileName);
1263 
1264         numDeps++;
1265         bufLen += strlen(cacheFileName) +1;
1266     }
1267 
1268     bufLen += 4*4 + numDeps * (4+kSHA1DigestLen);
1269 
1270     buf = malloc(bufLen);
1271 
1272     set4LE(buf+0, modWhen);
1273     set4LE(buf+4, crc);
1274     set4LE(buf+8, DALVIK_VM_BUILD);
1275     set4LE(buf+12, numDeps);
1276 
1277     // TODO: do we want to add dvmGetInlineOpsTableLength() here?  Won't
1278     // help us if somebody replaces an existing entry, but it'd catch
1279     // additions/removals.
1280 
1281     u1* ptr = buf + 4*4;
1282     for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) {
1283         const char* cacheFileName =
1284             dvmPathToAbsolutePortion(getCacheFileName(cpe));
1285         assert(cacheFileName != NULL); /* guaranteed by Class.c */
1286 
1287         const u1* signature = getSignature(cpe);
1288         int len = strlen(cacheFileName) +1;
1289 
1290         if (ptr + 4 + len + kSHA1DigestLen > buf + bufLen) {
1291             LOGE("DexOpt: overran buffer\n");
1292             dvmAbort();
1293         }
1294 
1295         set4LE(ptr, len);
1296         ptr += 4;
1297         memcpy(ptr, cacheFileName, len);
1298         ptr += len;
1299         memcpy(ptr, signature, kSHA1DigestLen);
1300         ptr += kSHA1DigestLen;
1301     }
1302 
1303     assert(ptr == buf + bufLen);
1304 
1305     result = sysWriteFully(fd, buf, bufLen, "DexOpt dep info");
1306 
1307     free(buf);
1308     return result;
1309 }
1310 
1311 
1312 /*
1313  * Write a block of data in "chunk" format.
1314  *
1315  * The chunk header fields are always in "native" byte order.  If "size"
1316  * is not a multiple of 8 bytes, the data area is padded out.
1317  */
writeChunk(int fd,u4 type,const void * data,size_t size)1318 static bool writeChunk(int fd, u4 type, const void* data, size_t size)
1319 {
1320     union {             /* save a syscall by grouping these together */
1321         char raw[8];
1322         struct {
1323             u4 type;
1324             u4 size;
1325         } ts;
1326     } header;
1327 
1328     assert(sizeof(header) == 8);
1329 
1330     LOGV("Writing chunk, type=%.4s size=%d\n", (char*) &type, size);
1331 
1332     header.ts.type = type;
1333     header.ts.size = (u4) size;
1334     if (sysWriteFully(fd, &header, sizeof(header),
1335             "DexOpt opt chunk header write") != 0)
1336     {
1337         return false;
1338     }
1339 
1340     if (size > 0) {
1341         if (sysWriteFully(fd, data, size, "DexOpt opt chunk write") != 0)
1342             return false;
1343     }
1344 
1345     /* if necessary, pad to 64-bit alignment */
1346     if ((size & 7) != 0) {
1347         int padSize = 8 - (size & 7);
1348         LOGV("size was %d, inserting %d pad bytes\n", size, padSize);
1349         lseek(fd, padSize, SEEK_CUR);
1350     }
1351 
1352     assert( ((int)lseek(fd, 0, SEEK_CUR) & 7) == 0);
1353 
1354     return true;
1355 }
1356 
1357 /*
1358  * Write opt data.
1359  *
1360  * We have different pieces, some of which may be optional.  To make the
1361  * most effective use of space, we use a "chunk" format, with a 4-byte
1362  * type and a 4-byte length.  We guarantee 64-bit alignment for the data,
1363  * so it can be used directly when the file is mapped for reading.
1364  */
writeOptData(int fd,const DexClassLookup * pClassLookup,const RegisterMapBuilder * pRegMapBuilder)1365 static bool writeOptData(int fd, const DexClassLookup* pClassLookup,
1366     const RegisterMapBuilder* pRegMapBuilder)
1367 {
1368     /* pre-computed class lookup hash table */
1369     if (!writeChunk(fd, (u4) kDexChunkClassLookup,
1370             pClassLookup, pClassLookup->size))
1371     {
1372         return false;
1373     }
1374 
1375     /* register maps (optional) */
1376     if (pRegMapBuilder != NULL) {
1377         if (!writeChunk(fd, (u4) kDexChunkRegisterMaps,
1378                 pRegMapBuilder->data, pRegMapBuilder->size))
1379         {
1380             return false;
1381         }
1382     }
1383 
1384     /* write the end marker */
1385     if (!writeChunk(fd, (u4) kDexChunkEnd, NULL, 0)) {
1386         return false;
1387     }
1388 
1389     return true;
1390 }
1391 
1392 /*
1393  * Compute a checksum on a piece of an open file.
1394  *
1395  * File will be positioned at end of checksummed area.
1396  *
1397  * Returns "true" on success.
1398  */
computeFileChecksum(int fd,off_t start,size_t length,u4 * pSum)1399 static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum)
1400 {
1401     unsigned char readBuf[8192];
1402     ssize_t actual;
1403     uLong adler;
1404 
1405     if (lseek(fd, start, SEEK_SET) != start) {
1406         LOGE("Unable to seek to start of checksum area (%ld): %s\n",
1407             (long) start, strerror(errno));
1408         return false;
1409     }
1410 
1411     adler = adler32(0L, Z_NULL, 0);
1412 
1413     while (length != 0) {
1414         size_t wanted = (length < sizeof(readBuf)) ? length : sizeof(readBuf);
1415         actual = read(fd, readBuf, wanted);
1416         if (actual <= 0) {
1417             LOGE("Read failed (%d) while computing checksum (len=%zu): %s\n",
1418                 (int) actual, length, strerror(errno));
1419             return false;
1420         }
1421 
1422         adler = adler32(adler, readBuf, actual);
1423 
1424         length -= actual;
1425     }
1426 
1427     *pSum = adler;
1428     return true;
1429 }
1430 
1431 /*
1432  * Update the Adler-32 checksum stored in the DEX file.  This covers the
1433  * swapped and optimized DEX data, but does not include the opt header
1434  * or optimized data.
1435  */
updateChecksum(u1 * addr,int len,DexHeader * pHeader)1436 static void updateChecksum(u1* addr, int len, DexHeader* pHeader)
1437 {
1438     /*
1439      * Rewrite the checksum.  We leave the SHA-1 signature alone.
1440      */
1441     uLong adler = adler32(0L, Z_NULL, 0);
1442     const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum);
1443 
1444     adler = adler32(adler, addr + nonSum, len - nonSum);
1445     pHeader->checksum = adler;
1446 }
1447