DexPrepare.cpp revision 64896a2543ee54e47c586f4cf26f54e7fdb366bd
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 */ 45static bool rewriteDex(u1* addr, int len, u4* pHeaderFlags, 46 DexClassLookup** ppClassLookup); 47static bool loadAllClasses(DvmDex* pDvmDex); 48static void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify, 49 bool doOpt); 50static void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz, 51 const DexClassDef* pClassDef, bool doVerify, bool doOpt); 52static void updateChecksum(u1* addr, int len, DexHeader* pHeader); 53static int writeDependencies(int fd, u4 modWhen, u4 crc); 54static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,\ 55 const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder); 56static 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 */ 82int 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 91retry: 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("Stale deps in cache file; removing and retrying\n"); 232 if (ftruncate(fd, 0) != 0) { 233 LOGW("Warning: unable to truncate cache file '%s': %s\n", 234 cacheFileName, strerror(errno)); 235 /* keep going */ 236 } 237 if (unlink(cacheFileName) != 0) { 238 LOGW("Warning: unable to remove cache file '%s': %d %s\n", 239 cacheFileName, errno, strerror(errno)); 240 /* keep going; permission failure should probably be fatal */ 241 } 242 LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName); 243 flock(fd, LOCK_UN); 244 close(fd); 245 goto retry; 246 } else { 247 LOGV("DexOpt: good deps in cache file\n"); 248 } 249 } 250 251 assert(fd >= 0); 252 return fd; 253 254close_fail: 255 flock(fd, LOCK_UN); 256 close(fd); 257 return -1; 258} 259 260/* 261 * Unlock the file descriptor. 262 * 263 * Returns "true" on success. 264 */ 265bool dvmUnlockCachedDexFile(int fd) 266{ 267 LOGVV("DexOpt: unlocking cache file fd=%d\n", fd); 268 return (flock(fd, LOCK_UN) == 0); 269} 270 271 272/* 273 * Given a descriptor for a file with DEX data in it, produce an 274 * optimized version. 275 * 276 * The file pointed to by "fd" is expected to be a locked shared resource 277 * (or private); we make no efforts to enforce multi-process correctness 278 * here. 279 * 280 * "fileName" is only used for debug output. "modWhen" and "crc" are stored 281 * in the dependency set. 282 * 283 * The "isBootstrap" flag determines how the optimizer and verifier handle 284 * package-scope access checks. When optimizing, we only load the bootstrap 285 * class DEX files and the target DEX, so the flag determines whether the 286 * target DEX classes are given a (synthetic) non-NULL classLoader pointer. 287 * This only really matters if the target DEX contains classes that claim to 288 * be in the same package as bootstrap classes. 289 * 290 * The optimizer will need to load every class in the target DEX file. 291 * This is generally undesirable, so we start a subprocess to do the 292 * work and wait for it to complete. 293 * 294 * Returns "true" on success. All data will have been written to "fd". 295 */ 296bool dvmOptimizeDexFile(int fd, off_t dexOffset, long dexLength, 297 const char* fileName, u4 modWhen, u4 crc, bool isBootstrap) 298{ 299 const char* lastPart = strrchr(fileName, '/'); 300 if (lastPart != NULL) 301 lastPart++; 302 else 303 lastPart = fileName; 304 305 LOGD("DexOpt: --- BEGIN '%s' (bootstrap=%d) ---\n", lastPart, isBootstrap); 306 307 pid_t pid; 308 309 /* 310 * This could happen if something in our bootclasspath, which we thought 311 * was all optimized, got rejected. 312 */ 313 if (gDvm.optimizing) { 314 LOGW("Rejecting recursive optimization attempt on '%s'\n", fileName); 315 return false; 316 } 317 318 pid = fork(); 319 if (pid == 0) { 320 static const int kUseValgrind = 0; 321 static const char* kDexOptBin = "/bin/dexopt"; 322 static const char* kValgrinder = "/usr/bin/valgrind"; 323 static const int kFixedArgCount = 10; 324 static const int kValgrindArgCount = 5; 325 static const int kMaxIntLen = 12; // '-'+10dig+'\0' -OR- 0x+8dig 326 int bcpSize = dvmGetBootPathSize(); 327 int argc = kFixedArgCount + bcpSize 328 + (kValgrindArgCount * kUseValgrind); 329 char* argv[argc+1]; // last entry is NULL 330 char values[argc][kMaxIntLen]; 331 char* execFile; 332 char* androidRoot; 333 int flags; 334 335 /* change process groups, so we don't clash with ProcessManager */ 336 setpgid(0, 0); 337 338 /* full path to optimizer */ 339 androidRoot = getenv("ANDROID_ROOT"); 340 if (androidRoot == NULL) { 341 LOGW("ANDROID_ROOT not set, defaulting to /system\n"); 342 androidRoot = "/system"; 343 } 344 execFile = malloc(strlen(androidRoot) + strlen(kDexOptBin) + 1); 345 strcpy(execFile, androidRoot); 346 strcat(execFile, kDexOptBin); 347 348 /* 349 * Create arg vector. 350 */ 351 int curArg = 0; 352 353 if (kUseValgrind) { 354 /* probably shouldn't ship the hard-coded path */ 355 argv[curArg++] = (char*)kValgrinder; 356 argv[curArg++] = "--tool=memcheck"; 357 argv[curArg++] = "--leak-check=yes"; // check for leaks too 358 argv[curArg++] = "--leak-resolution=med"; // increase from 2 to 4 359 argv[curArg++] = "--num-callers=16"; // default is 12 360 assert(curArg == kValgrindArgCount); 361 } 362 argv[curArg++] = execFile; 363 364 argv[curArg++] = "--dex"; 365 366 sprintf(values[2], "%d", DALVIK_VM_BUILD); 367 argv[curArg++] = values[2]; 368 369 sprintf(values[3], "%d", fd); 370 argv[curArg++] = values[3]; 371 372 sprintf(values[4], "%d", (int) dexOffset); 373 argv[curArg++] = values[4]; 374 375 sprintf(values[5], "%d", (int) dexLength); 376 argv[curArg++] = values[5]; 377 378 argv[curArg++] = (char*)fileName; 379 380 sprintf(values[7], "%d", (int) modWhen); 381 argv[curArg++] = values[7]; 382 383 sprintf(values[8], "%d", (int) crc); 384 argv[curArg++] = values[8]; 385 386 flags = 0; 387 if (gDvm.dexOptMode != OPTIMIZE_MODE_NONE) { 388 flags |= DEXOPT_OPT_ENABLED; 389 if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL) 390 flags |= DEXOPT_OPT_ALL; 391 } 392 if (gDvm.classVerifyMode != VERIFY_MODE_NONE) { 393 flags |= DEXOPT_VERIFY_ENABLED; 394 if (gDvm.classVerifyMode == VERIFY_MODE_ALL) 395 flags |= DEXOPT_VERIFY_ALL; 396 } 397 if (isBootstrap) 398 flags |= DEXOPT_IS_BOOTSTRAP; 399 if (gDvm.generateRegisterMaps) 400 flags |= DEXOPT_GEN_REGISTER_MAP; 401 sprintf(values[9], "%d", flags); 402 argv[curArg++] = values[9]; 403 404 assert(((!kUseValgrind && curArg == kFixedArgCount) || 405 ((kUseValgrind && curArg == kFixedArgCount+kValgrindArgCount)))); 406 407 ClassPathEntry* cpe; 408 for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 409 argv[curArg++] = cpe->fileName; 410 } 411 assert(curArg == argc); 412 413 argv[curArg] = NULL; 414 415 if (kUseValgrind) 416 execv(kValgrinder, argv); 417 else 418 execv(execFile, argv); 419 420 LOGE("execv '%s'%s failed: %s\n", execFile, 421 kUseValgrind ? " [valgrind]" : "", strerror(errno)); 422 exit(1); 423 } else { 424 LOGV("DexOpt: waiting for verify+opt, pid=%d\n", (int) pid); 425 int status; 426 pid_t gotPid; 427 int oldStatus; 428 429 /* 430 * Wait for the optimization process to finish. We go into VMWAIT 431 * mode here so GC suspension won't have to wait for us. 432 */ 433 oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 434 while (true) { 435 gotPid = waitpid(pid, &status, 0); 436 if (gotPid == -1 && errno == EINTR) { 437 LOGD("waitpid interrupted, retrying\n"); 438 } else { 439 break; 440 } 441 } 442 dvmChangeStatus(NULL, oldStatus); 443 if (gotPid != pid) { 444 LOGE("waitpid failed: wanted %d, got %d: %s\n", 445 (int) pid, (int) gotPid, strerror(errno)); 446 return false; 447 } 448 449 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 450 LOGD("DexOpt: --- END '%s' (success) ---\n", lastPart); 451 return true; 452 } else { 453 LOGW("DexOpt: --- END '%s' --- status=0x%04x, process failed\n", 454 lastPart, status); 455 return false; 456 } 457 } 458} 459 460/* 461 * Do the actual optimization. This is executed in the dexopt process. 462 * 463 * For best use of disk/memory, we want to extract once and perform 464 * optimizations in place. If the file has to expand or contract 465 * to match local structure padding/alignment expectations, we want 466 * to do the rewrite as part of the extract, rather than extracting 467 * into a temp file and slurping it back out. (The structure alignment 468 * is currently correct for all platforms, and this isn't expected to 469 * change, so we should be okay with having it already extracted.) 470 * 471 * Returns "true" on success. 472 */ 473bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength, 474 const char* fileName, u4 modWhen, u4 crc, bool isBootstrap) 475{ 476 DexClassLookup* pClassLookup = NULL; 477 IndexMapSet* pIndexMapSet = 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, scan the instructions, looking 547 * for ways to reduce the size of the resolved-constant table. 548 * This is done post-optimization, across the instructions 549 * in all methods in all classes (even the ones that failed 550 * to load). 551 */ 552 pIndexMapSet = dvmRewriteConstants(pDvmDex); 553 554 /* 555 * If configured to do so, generate register map output 556 * for all verified classes. The register maps were 557 * generated during verification, and will now be serialized. 558 */ 559 if (gDvm.generateRegisterMaps) { 560 pRegMapBuilder = dvmGenerateRegisterMaps(pDvmDex); 561 if (pRegMapBuilder == NULL) { 562 LOGE("Failed generating register maps\n"); 563 success = false; 564 } 565 } 566 567 DexHeader* pHeader = (DexHeader*)pDvmDex->pHeader; 568 updateChecksum(dexAddr, dexLength, pHeader); 569 570 dvmDexFileFree(pDvmDex); 571 } 572 } 573 574 /* unmap the read-write version, forcing writes to disk */ 575 if (msync(mapAddr, dexOffset + dexLength, MS_SYNC) != 0) { 576 LOGW("msync failed: %s\n", strerror(errno)); 577 // weird, but keep going 578 } 579#if 1 580 /* 581 * This causes clean shutdown to fail, because we have loaded classes 582 * that point into it. For the optimizer this isn't a problem, 583 * because it's more efficient for the process to simply exit. 584 * Exclude this code when doing clean shutdown for valgrind. 585 */ 586 if (munmap(mapAddr, dexOffset + dexLength) != 0) { 587 LOGE("munmap failed: %s\n", strerror(errno)); 588 goto bail; 589 } 590#endif 591 592 if (!success) 593 goto bail; 594 } 595 596 /* get start offset, and adjust deps start for 64-bit alignment */ 597 off_t depsOffset, auxOffset, endOffset, adjOffset; 598 int depsLength, auxLength; 599 u4 optChecksum; 600 601 depsOffset = lseek(fd, 0, SEEK_END); 602 if (depsOffset < 0) { 603 LOGE("lseek to EOF failed: %s\n", strerror(errno)); 604 goto bail; 605 } 606 adjOffset = (depsOffset + 7) & ~(0x07); 607 if (adjOffset != depsOffset) { 608 LOGV("Adjusting deps start from %d to %d\n", 609 (int) depsOffset, (int) adjOffset); 610 depsOffset = adjOffset; 611 lseek(fd, depsOffset, SEEK_SET); 612 } 613 614 /* 615 * Append the dependency list. 616 */ 617 if (writeDependencies(fd, modWhen, crc) != 0) { 618 LOGW("Failed writing dependencies\n"); 619 goto bail; 620 } 621 622 /* compute deps length, then adjust aux start for 64-bit alignment */ 623 auxOffset = lseek(fd, 0, SEEK_END); 624 depsLength = auxOffset - depsOffset; 625 626 adjOffset = (auxOffset + 7) & ~(0x07); 627 if (adjOffset != auxOffset) { 628 LOGV("Adjusting aux start from %d to %d\n", 629 (int) auxOffset, (int) adjOffset); 630 auxOffset = adjOffset; 631 lseek(fd, auxOffset, SEEK_SET); 632 } 633 634 /* 635 * Append any auxillary pre-computed data structures. 636 */ 637 if (!writeAuxData(fd, pClassLookup, pIndexMapSet, pRegMapBuilder)) { 638 LOGW("Failed writing aux data\n"); 639 goto bail; 640 } 641 642 endOffset = lseek(fd, 0, SEEK_END); 643 auxLength = endOffset - auxOffset; 644 645 /* compute checksum from start of deps to end of aux area */ 646 if (!computeFileChecksum(fd, depsOffset, 647 (auxOffset+auxLength) - depsOffset, &optChecksum)) 648 { 649 goto bail; 650 } 651 652 /* 653 * Output the "opt" header with all values filled in and a correct 654 * magic number. 655 */ 656 DexOptHeader optHdr; 657 memset(&optHdr, 0xff, sizeof(optHdr)); 658 memcpy(optHdr.magic, DEX_OPT_MAGIC, 4); 659 memcpy(optHdr.magic+4, DEX_OPT_MAGIC_VERS, 4); 660 optHdr.dexOffset = (u4) dexOffset; 661 optHdr.dexLength = (u4) dexLength; 662 optHdr.depsOffset = (u4) depsOffset; 663 optHdr.depsLength = (u4) depsLength; 664 optHdr.auxOffset = (u4) auxOffset; 665 optHdr.auxLength = (u4) auxLength; 666 667 optHdr.flags = headerFlags; 668 optHdr.checksum = optChecksum; 669 670 ssize_t actual; 671 lseek(fd, 0, SEEK_SET); 672 if (sysWriteFully(fd, &optHdr, sizeof(optHdr), "DexOpt opt header") != 0) 673 goto bail; 674 675 LOGV("Successfully wrote DEX header\n"); 676 result = true; 677 678 //dvmRegisterMapDumpStats(); 679 680bail: 681 dvmFreeIndexMapSet(pIndexMapSet); 682 dvmFreeRegisterMapBuilder(pRegMapBuilder); 683 free(pClassLookup); 684 return result; 685} 686 687 688/* 689 * Perform in-place rewrites on a memory-mapped DEX file. 690 * 691 * This happens in a short-lived child process, so we can go nutty with 692 * loading classes and allocating memory. 693 */ 694static bool rewriteDex(u1* addr, int len, u4* pHeaderFlags, 695 DexClassLookup** ppClassLookup) 696{ 697 u8 prepWhen, loadWhen, verifyOptWhen; 698 DvmDex* pDvmDex = NULL; 699 bool doVerify, doOpt; 700 bool result = false; 701 702 *pHeaderFlags = 0; 703 704 /* if the DEX is in the wrong byte order, swap it now */ 705 if (dexFixByteOrdering(addr, len) != 0) 706 goto bail; 707#if __BYTE_ORDER != __LITTLE_ENDIAN 708 *pHeaderFlags |= DEX_OPT_FLAG_BIG; 709#endif 710 711 if (gDvm.classVerifyMode == VERIFY_MODE_NONE) 712 doVerify = false; 713 else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) 714 doVerify = !gDvm.optimizingBootstrapClass; 715 else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ 716 doVerify = true; 717 718 if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) 719 doOpt = false; 720 else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED) 721 doOpt = doVerify; 722 else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ 723 doOpt = true; 724 725 /* TODO: decide if this is actually useful */ 726 if (doVerify) 727 *pHeaderFlags |= DEX_FLAG_VERIFIED; 728 if (doOpt) 729 *pHeaderFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS; 730 731 /* 732 * Now that the DEX file can be read directly, create a DexFile struct 733 * for it. 734 */ 735 if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) { 736 LOGE("Unable to create DexFile\n"); 737 goto bail; 738 } 739 740 /* 741 * Create the class lookup table. This will eventually be appended 742 * to the end of the .odex. 743 */ 744 *ppClassLookup = dexCreateClassLookup(pDvmDex->pDexFile); 745 if (*ppClassLookup == NULL) 746 goto bail; 747 748 /* 749 * If we're not going to attempt to verify or optimize the classes, 750 * there's no value in loading them, so bail out early. 751 */ 752 if (!doVerify && !doOpt) { 753 result = true; 754 goto bail; 755 } 756 757 /* this is needed for the next part */ 758 pDvmDex->pDexFile->pClassLookup = *ppClassLookup; 759 760 prepWhen = dvmGetRelativeTimeUsec(); 761 762 /* 763 * Load all classes found in this DEX file. If they fail to load for 764 * some reason, they won't get verified (which is as it should be). 765 */ 766 if (!loadAllClasses(pDvmDex)) 767 goto bail; 768 loadWhen = dvmGetRelativeTimeUsec(); 769 770 /* 771 * Verify and optimize all classes in the DEX file (command-line 772 * options permitting). 773 * 774 * This is best-effort, so there's really no way for dexopt to 775 * fail at this point. 776 */ 777 verifyAndOptimizeClasses(pDvmDex->pDexFile, doVerify, doOpt); 778 verifyOptWhen = dvmGetRelativeTimeUsec(); 779 780 const char* msgStr = "???"; 781 if (doVerify && doOpt) 782 msgStr = "verify+opt"; 783 else if (doVerify) 784 msgStr = "verify"; 785 else if (doOpt) 786 msgStr = "opt"; 787 LOGD("DexOpt: load %dms, %s %dms\n", 788 (int) (loadWhen - prepWhen) / 1000, 789 msgStr, 790 (int) (verifyOptWhen - loadWhen) / 1000); 791 792 result = true; 793 794bail: 795 /* free up storage */ 796 dvmDexFileFree(pDvmDex); 797 798 return result; 799} 800 801/* 802 * Try to load all classes in the specified DEX. If they have some sort 803 * of broken dependency, e.g. their superclass lives in a different DEX 804 * that wasn't previously loaded into the bootstrap class path, loading 805 * will fail. This is the desired behavior. 806 * 807 * We have no notion of class loader at this point, so we load all of 808 * the classes with the bootstrap class loader. It turns out this has 809 * exactly the behavior we want, and has no ill side effects because we're 810 * running in a separate process and anything we load here will be forgotten. 811 * 812 * We set the CLASS_MULTIPLE_DEFS flag here if we see multiple definitions. 813 * This works because we only call here as part of optimization / pre-verify, 814 * not during verification as part of loading a class into a running VM. 815 * 816 * This returns "false" if the world is too screwed up to do anything 817 * useful at all. 818 */ 819static bool loadAllClasses(DvmDex* pDvmDex) 820{ 821 u4 count = pDvmDex->pDexFile->pHeader->classDefsSize; 822 u4 idx; 823 int loaded = 0; 824 825 LOGV("DexOpt: +++ trying to load %d classes\n", count); 826 827 dvmSetBootPathExtraDex(pDvmDex); 828 829 /* 830 * We have some circularity issues with Class and Object that are most 831 * easily avoided by ensuring that Object is never the first thing we 832 * try to find. Take care of that here. (We only need to do this when 833 * loading classes from the DEX file that contains Object, and only 834 * when Object comes first in the list, but it costs very little to 835 * do it in all cases.) 836 */ 837 if (dvmFindSystemClass("Ljava/lang/Class;") == NULL) { 838 LOGE("ERROR: java.lang.Class does not exist!\n"); 839 return false; 840 } 841 842 for (idx = 0; idx < count; idx++) { 843 const DexClassDef* pClassDef; 844 const char* classDescriptor; 845 ClassObject* newClass; 846 847 pClassDef = dexGetClassDef(pDvmDex->pDexFile, idx); 848 classDescriptor = 849 dexStringByTypeIdx(pDvmDex->pDexFile, pClassDef->classIdx); 850 851 LOGV("+++ loading '%s'", classDescriptor); 852 //newClass = dvmDefineClass(pDexFile, classDescriptor, 853 // NULL); 854 newClass = dvmFindSystemClassNoInit(classDescriptor); 855 if (newClass == NULL) { 856 LOGV("DexOpt: failed loading '%s'\n", classDescriptor); 857 dvmClearOptException(dvmThreadSelf()); 858 } else if (newClass->pDvmDex != pDvmDex) { 859 /* 860 * We don't load the new one, and we tag the first one found 861 * with the "multiple def" flag so the resolver doesn't try 862 * to make it available. 863 */ 864 LOGD("DexOpt: '%s' has an earlier definition; blocking out\n", 865 classDescriptor); 866 SET_CLASS_FLAG(newClass, CLASS_MULTIPLE_DEFS); 867 } else { 868 loaded++; 869 } 870 } 871 LOGV("DexOpt: +++ successfully loaded %d classes\n", loaded); 872 873 dvmSetBootPathExtraDex(NULL); 874 return true; 875} 876 877/* 878 * Verify and/or optimize all classes that were successfully loaded from 879 * this DEX file. 880 */ 881static void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify, 882 bool doOpt) 883{ 884 u4 count = pDexFile->pHeader->classDefsSize; 885 u4 idx; 886 887 /* 888 * Create a data structure for use by the bytecode optimizer. We 889 * stuff it into a global so we don't have to pass it around as 890 * a function argument. 891 * 892 * We could create this at VM startup, but there's no need to do so 893 * unless we're optimizing, which means we're in dexopt, and we're 894 * only going to call here once. 895 */ 896 if (doOpt) { 897 gDvm.inlineSubs = dvmCreateInlineSubsTable(); 898 if (gDvm.inlineSubs == NULL) 899 return; 900 } 901 902 for (idx = 0; idx < count; idx++) { 903 const DexClassDef* pClassDef; 904 const char* classDescriptor; 905 ClassObject* clazz; 906 907 pClassDef = dexGetClassDef(pDexFile, idx); 908 classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); 909 910 /* all classes are loaded into the bootstrap class loader */ 911 clazz = dvmLookupClass(classDescriptor, NULL, false); 912 if (clazz != NULL) { 913 verifyAndOptimizeClass(pDexFile, clazz, pClassDef, doVerify, doOpt); 914 915 } else { 916 // TODO: log when in verbose mode 917 LOGV("DexOpt: not optimizing unavailable class '%s'\n", 918 classDescriptor); 919 } 920 } 921 922 if (gDvm.inlineSubs != NULL) { 923 dvmFreeInlineSubsTable(gDvm.inlineSubs); 924 gDvm.inlineSubs = NULL; 925 } 926} 927 928/* 929 * Verify and/or optimize a specific class. 930 */ 931static void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz, 932 const DexClassDef* pClassDef, bool doVerify, bool doOpt) 933{ 934 const char* classDescriptor; 935 bool verified = false; 936 937 classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); 938 939 /* 940 * First, try to verify it. 941 */ 942 if (doVerify) { 943 if (clazz->pDvmDex->pDexFile != pDexFile) { 944 LOGD("DexOpt: not verifying '%s': multiple definitions\n", 945 classDescriptor); 946 } else { 947 if (dvmVerifyClass(clazz, VERIFY_DEFAULT)) { 948 /* 949 * Set the "is preverified" flag in the DexClassDef. We 950 * do it here, rather than in the ClassObject structure, 951 * because the DexClassDef is part of the odex file. 952 */ 953 assert((clazz->accessFlags & JAVA_FLAGS_MASK) == 954 pClassDef->accessFlags); 955 ((DexClassDef*)pClassDef)->accessFlags |= 956 CLASS_ISPREVERIFIED; 957 verified = true; 958 } else { 959 // TODO: log when in verbose mode 960 LOGV("DexOpt: '%s' failed verification\n", classDescriptor); 961 } 962 } 963 } 964 965 if (doOpt) { 966 if (!verified && gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED) { 967 LOGV("DexOpt: not optimizing '%s': not verified\n", 968 classDescriptor); 969 } else { 970 dvmOptimizeClass(clazz); 971 972 /* set the flag whether or not we actually changed anything */ 973 ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISOPTIMIZED; 974 } 975 } 976} 977 978 979/* 980 * Get the cache file name from a ClassPathEntry. 981 */ 982static const char* getCacheFileName(const ClassPathEntry* cpe) 983{ 984 switch (cpe->kind) { 985 case kCpeJar: 986 return dvmGetJarFileCacheFileName((JarFile*) cpe->ptr); 987 case kCpeDex: 988 return dvmGetRawDexFileCacheFileName((RawDexFile*) cpe->ptr); 989 default: 990 LOGE("DexOpt: unexpected cpe kind %d\n", cpe->kind); 991 dvmAbort(); 992 return NULL; 993 } 994} 995 996/* 997 * Get the SHA-1 signature. 998 */ 999static const u1* getSignature(const ClassPathEntry* cpe) 1000{ 1001 DvmDex* pDvmDex; 1002 1003 switch (cpe->kind) { 1004 case kCpeJar: 1005 pDvmDex = dvmGetJarFileDex((JarFile*) cpe->ptr); 1006 break; 1007 case kCpeDex: 1008 pDvmDex = dvmGetRawDexFileDex((RawDexFile*) cpe->ptr); 1009 break; 1010 default: 1011 LOGE("unexpected cpe kind %d\n", cpe->kind); 1012 dvmAbort(); 1013 pDvmDex = NULL; // make gcc happy 1014 } 1015 1016 assert(pDvmDex != NULL); 1017 return pDvmDex->pDexFile->pHeader->signature; 1018} 1019 1020 1021/* 1022 * Dependency layout: 1023 * 4b Source file modification time, in seconds since 1970 UTC 1024 * 4b CRC-32 from Zip entry, or Adler32 from source DEX header 1025 * 4b Dalvik VM build number 1026 * 4b Number of dependency entries that follow 1027 * Dependency entries: 1028 * 4b Name length (including terminating null) 1029 * var Full path of cache entry (null terminated) 1030 * 20b SHA-1 signature from source DEX file 1031 * 1032 * If this changes, update DEX_OPT_MAGIC_VERS. 1033 */ 1034static const size_t kMinDepSize = 4 * 4; 1035static const size_t kMaxDepSize = 4 * 4 + 1024; // sanity check 1036 1037/* 1038 * Read the "opt" header, verify it, then read the dependencies section 1039 * and verify that data as well. 1040 * 1041 * If "sourceAvail" is "true", this will verify that "modWhen" and "crc" 1042 * match up with what is stored in the header. If they don't, we reject 1043 * the file so that it can be recreated from the updated original. If 1044 * "sourceAvail" isn't set, e.g. for a .odex file, we ignore these arguments. 1045 * 1046 * On successful return, the file will be seeked immediately past the 1047 * "opt" header. 1048 */ 1049bool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen, 1050 u4 crc, bool expectVerify, bool expectOpt) 1051{ 1052 DexOptHeader optHdr; 1053 u1* depData = NULL; 1054 const u1* magic; 1055 off_t posn; 1056 int result = false; 1057 ssize_t actual; 1058 1059 /* 1060 * Start at the start. The "opt" header, when present, will always be 1061 * the first thing in the file. 1062 */ 1063 if (lseek(fd, 0, SEEK_SET) != 0) { 1064 LOGE("DexOpt: failed to seek to start of file: %s\n", strerror(errno)); 1065 goto bail; 1066 } 1067 1068 /* 1069 * Read and do trivial verification on the opt header. The header is 1070 * always in host byte order. 1071 */ 1072 if (read(fd, &optHdr, sizeof(optHdr)) != sizeof(optHdr)) { 1073 LOGE("DexOpt: failed reading opt header: %s\n", strerror(errno)); 1074 goto bail; 1075 } 1076 1077 magic = optHdr.magic; 1078 if (memcmp(magic, DEX_OPT_MAGIC, 4) != 0) { 1079 /* not a DEX file, or previous attempt was interrupted */ 1080 LOGD("DexOpt: incorrect opt magic number (0x%02x %02x %02x %02x)\n", 1081 magic[0], magic[1], magic[2], magic[3]); 1082 goto bail; 1083 } 1084 if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) { 1085 LOGW("DexOpt: stale opt version (0x%02x %02x %02x %02x)\n", 1086 magic[4], magic[5], magic[6], magic[7]); 1087 goto bail; 1088 } 1089 if (optHdr.depsLength < kMinDepSize || optHdr.depsLength > kMaxDepSize) { 1090 LOGW("DexOpt: weird deps length %d, bailing\n", optHdr.depsLength); 1091 goto bail; 1092 } 1093 1094 /* 1095 * Do the header flags match up with what we want? 1096 * 1097 * This is useful because it allows us to automatically regenerate 1098 * a file when settings change (e.g. verification is now mandatory), 1099 * but can cause difficulties if the bootstrap classes we depend upon 1100 * were handled differently than the current options specify. We get 1101 * upset because they're not verified or optimized, but we're not able 1102 * to regenerate them because the installer won't let us. 1103 * 1104 * (This is also of limited value when !sourceAvail.) 1105 * 1106 * So, for now, we essentially ignore "expectVerify" and "expectOpt" 1107 * by limiting the match mask. 1108 * 1109 * The only thing we really can't handle is incorrect byte-ordering. 1110 */ 1111 const u4 matchMask = DEX_OPT_FLAG_BIG; 1112 u4 expectedFlags = 0; 1113#if __BYTE_ORDER != __LITTLE_ENDIAN 1114 expectedFlags |= DEX_OPT_FLAG_BIG; 1115#endif 1116 if (expectVerify) 1117 expectedFlags |= DEX_FLAG_VERIFIED; 1118 if (expectOpt) 1119 expectedFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS; 1120 if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) { 1121 LOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)\n", 1122 expectedFlags, optHdr.flags, matchMask); 1123 goto bail; 1124 } 1125 1126 posn = lseek(fd, optHdr.depsOffset, SEEK_SET); 1127 if (posn < 0) { 1128 LOGW("DexOpt: seek to deps failed: %s\n", strerror(errno)); 1129 goto bail; 1130 } 1131 1132 /* 1133 * Read all of the dependency stuff into memory. 1134 */ 1135 depData = (u1*) malloc(optHdr.depsLength); 1136 if (depData == NULL) { 1137 LOGW("DexOpt: unable to allocate %d bytes for deps\n", 1138 optHdr.depsLength); 1139 goto bail; 1140 } 1141 actual = read(fd, depData, optHdr.depsLength); 1142 if (actual != (ssize_t) optHdr.depsLength) { 1143 LOGW("DexOpt: failed reading deps: %d of %d (err=%s)\n", 1144 (int) actual, optHdr.depsLength, strerror(errno)); 1145 goto bail; 1146 } 1147 1148 /* 1149 * Verify simple items. 1150 */ 1151 const u1* ptr; 1152 u4 val; 1153 1154 ptr = depData; 1155 val = read4LE(&ptr); 1156 if (sourceAvail && val != modWhen) { 1157 LOGI("DexOpt: source file mod time mismatch (%08x vs %08x)\n", 1158 val, modWhen); 1159 goto bail; 1160 } 1161 val = read4LE(&ptr); 1162 if (sourceAvail && val != crc) { 1163 LOGI("DexOpt: source file CRC mismatch (%08x vs %08x)\n", val, crc); 1164 goto bail; 1165 } 1166 val = read4LE(&ptr); 1167 if (val != DALVIK_VM_BUILD) { 1168 LOGD("DexOpt: VM build version mismatch (%d vs %d)\n", 1169 val, DALVIK_VM_BUILD); 1170 goto bail; 1171 } 1172 1173 /* 1174 * Verify dependencies on other cached DEX files. It must match 1175 * exactly with what is currently defined in the bootclasspath. 1176 */ 1177 ClassPathEntry* cpe; 1178 u4 numDeps; 1179 1180 numDeps = read4LE(&ptr); 1181 LOGV("+++ DexOpt: numDeps = %d\n", numDeps); 1182 for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 1183 const char* cacheFileName = getCacheFileName(cpe); 1184 const u1* signature = getSignature(cpe); 1185 size_t len = strlen(cacheFileName) +1; 1186 u4 storedStrLen; 1187 1188 if (numDeps == 0) { 1189 /* more entries in bootclasspath than in deps list */ 1190 LOGI("DexOpt: not all deps represented\n"); 1191 goto bail; 1192 } 1193 1194 storedStrLen = read4LE(&ptr); 1195 if (len != storedStrLen || 1196 strcmp(cacheFileName, (const char*) ptr) != 0) 1197 { 1198 LOGI("DexOpt: mismatch dep name: '%s' vs. '%s'\n", 1199 cacheFileName, ptr); 1200 goto bail; 1201 } 1202 1203 ptr += storedStrLen; 1204 1205 if (memcmp(signature, ptr, kSHA1DigestLen) != 0) { 1206 LOGI("DexOpt: mismatch dep signature for '%s'\n", cacheFileName); 1207 goto bail; 1208 } 1209 ptr += kSHA1DigestLen; 1210 1211 LOGV("DexOpt: dep match on '%s'\n", cacheFileName); 1212 1213 numDeps--; 1214 } 1215 1216 if (numDeps != 0) { 1217 /* more entries in deps list than in classpath */ 1218 LOGI("DexOpt: Some deps went away\n"); 1219 goto bail; 1220 } 1221 1222 // consumed all data and no more? 1223 if (ptr != depData + optHdr.depsLength) { 1224 LOGW("DexOpt: Spurious dep data? %d vs %d\n", 1225 (int) (ptr - depData), optHdr.depsLength); 1226 assert(false); 1227 } 1228 1229 result = true; 1230 1231bail: 1232 free(depData); 1233 return result; 1234} 1235 1236/* 1237 * Write the dependency info to "fd" at the current file position. 1238 */ 1239static int writeDependencies(int fd, u4 modWhen, u4 crc) 1240{ 1241 u1* buf = NULL; 1242 ssize_t actual; 1243 int result = -1; 1244 ssize_t bufLen; 1245 ClassPathEntry* cpe; 1246 int i, numDeps; 1247 1248 /* 1249 * Count up the number of completed entries in the bootclasspath. 1250 */ 1251 numDeps = 0; 1252 bufLen = 0; 1253 for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 1254 const char* cacheFileName = getCacheFileName(cpe); 1255 LOGV("+++ DexOpt: found dep '%s'\n", cacheFileName); 1256 1257 numDeps++; 1258 bufLen += strlen(cacheFileName) +1; 1259 } 1260 1261 bufLen += 4*4 + numDeps * (4+kSHA1DigestLen); 1262 1263 buf = malloc(bufLen); 1264 1265 set4LE(buf+0, modWhen); 1266 set4LE(buf+4, crc); 1267 set4LE(buf+8, DALVIK_VM_BUILD); 1268 set4LE(buf+12, numDeps); 1269 1270 // TODO: do we want to add dvmGetInlineOpsTableLength() here? Won't 1271 // help us if somebody replaces an existing entry, but it'd catch 1272 // additions/removals. 1273 1274 u1* ptr = buf + 4*4; 1275 for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 1276 const char* cacheFileName = getCacheFileName(cpe); 1277 const u1* signature = getSignature(cpe); 1278 int len = strlen(cacheFileName) +1; 1279 1280 if (ptr + 4 + len + kSHA1DigestLen > buf + bufLen) { 1281 LOGE("DexOpt: overran buffer\n"); 1282 dvmAbort(); 1283 } 1284 1285 set4LE(ptr, len); 1286 ptr += 4; 1287 memcpy(ptr, cacheFileName, len); 1288 ptr += len; 1289 memcpy(ptr, signature, kSHA1DigestLen); 1290 ptr += kSHA1DigestLen; 1291 } 1292 1293 assert(ptr == buf + bufLen); 1294 1295 result = sysWriteFully(fd, buf, bufLen, "DexOpt dep info"); 1296 1297 free(buf); 1298 return result; 1299} 1300 1301 1302/* 1303 * Write a block of data in "chunk" format. 1304 * 1305 * The chunk header fields are always in "native" byte order. If "size" 1306 * is not a multiple of 8 bytes, the data area is padded out. 1307 */ 1308static bool writeChunk(int fd, u4 type, const void* data, size_t size) 1309{ 1310 ssize_t actual; 1311 union { /* save a syscall by grouping these together */ 1312 char raw[8]; 1313 struct { 1314 u4 type; 1315 u4 size; 1316 } ts; 1317 } header; 1318 1319 assert(sizeof(header) == 8); 1320 1321 LOGV("Writing chunk, type=%.4s size=%d\n", (char*) &type, size); 1322 1323 header.ts.type = type; 1324 header.ts.size = (u4) size; 1325 if (sysWriteFully(fd, &header, sizeof(header), 1326 "DexOpt aux chunk header write") != 0) 1327 { 1328 return false; 1329 } 1330 1331 if (size > 0) { 1332 if (sysWriteFully(fd, data, size, "DexOpt aux chunk write") != 0) 1333 return false; 1334 } 1335 1336 /* if necessary, pad to 64-bit alignment */ 1337 if ((size & 7) != 0) { 1338 int padSize = 8 - (size & 7); 1339 LOGV("size was %d, inserting %d pad bytes\n", size, padSize); 1340 lseek(fd, padSize, SEEK_CUR); 1341 } 1342 1343 assert( ((int)lseek(fd, 0, SEEK_CUR) & 7) == 0); 1344 1345 return true; 1346} 1347 1348/* 1349 * Write aux data. 1350 * 1351 * We have different pieces, some of which may be optional. To make the 1352 * most effective use of space, we use a "chunk" format, with a 4-byte 1353 * type and a 4-byte length. We guarantee 64-bit alignment for the data, 1354 * so it can be used directly when the file is mapped for reading. 1355 */ 1356static bool writeAuxData(int fd, const DexClassLookup* pClassLookup, 1357 const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder) 1358{ 1359 /* pre-computed class lookup hash table */ 1360 if (!writeChunk(fd, (u4) kDexChunkClassLookup, 1361 pClassLookup, pClassLookup->size)) 1362 { 1363 return false; 1364 } 1365 1366 /* remapped constants (optional) */ 1367 if (pIndexMapSet != NULL) { 1368 if (!writeChunk(fd, pIndexMapSet->chunkType, 1369 pIndexMapSet->chunkData, pIndexMapSet->chunkDataLen)) 1370 { 1371 return false; 1372 } 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 */ 1399static 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 auxillary data. 1435 */ 1436static 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 1448