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 writeOptData(int fd, const DexClassLookup* pClassLookup,\ 55 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("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 255close_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 */ 266bool 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 */ 297bool 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 */ 474bool 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 672bail: 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 */ 685static 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 785bail: 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 */ 810static 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 */ 872static 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 */ 922static 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 */ 972static 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 */ 989static 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 */ 1024static const size_t kMinDepSize = 4 * 4; 1025static 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 */ 1039bool 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 1236bail: 1237 free(depData); 1238 return result; 1239} 1240 1241/* 1242 * Write the dependency info to "fd" at the current file position. 1243 */ 1244static 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 */ 1318static 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 */ 1365static 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 */ 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 optimized 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