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