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 * Convert the output from "dx" into a locally-optimized DEX file. 19 * 20 * TODO: the format of the optimized header is currently "whatever we 21 * happen to write", since the VM that writes it is by definition the same 22 * as the VM that reads it. Still, it should be better documented and 23 * more rigorously structured. 24 */ 25#include "Dalvik.h" 26#include "libdex/InstrUtils.h" 27#include "libdex/OptInvocation.h" 28#include "analysis/RegisterMap.h" 29 30#include <zlib.h> 31 32#include <stdlib.h> 33#include <unistd.h> 34#include <sys/mman.h> 35#include <sys/stat.h> 36#include <sys/file.h> 37#include <sys/wait.h> 38#include <fcntl.h> 39#include <errno.h> 40 41/* 42 * Virtual/direct calls to "method" are replaced with an execute-inline 43 * instruction with index "idx". 44 */ 45typedef struct InlineSub { 46 Method* method; 47 int inlineIdx; 48} InlineSub; 49 50 51/* fwd */ 52static int writeDependencies(int fd, u4 modWhen, u4 crc); 53static bool writeAuxData(int fd, const DexClassLookup* pClassLookup,\ 54 const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder); 55static void logFailedWrite(size_t expected, ssize_t actual, const char* msg, 56 int err); 57static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum); 58 59static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt,\ 60 u4* pHeaderFlags, DexClassLookup** ppClassLookup); 61static void updateChecksum(u1* addr, int len, DexHeader* pHeader); 62static bool loadAllClasses(DvmDex* pDvmDex); 63static void optimizeLoadedClasses(DexFile* pDexFile); 64static void optimizeClass(ClassObject* clazz, const InlineSub* inlineSubs); 65static bool optimizeMethod(Method* method, const InlineSub* inlineSubs); 66static void rewriteInstField(Method* method, u2* insns, OpCode newOpc); 67static bool rewriteVirtualInvoke(Method* method, u2* insns, OpCode newOpc); 68static bool rewriteEmptyDirectInvoke(Method* method, u2* insns); 69static bool rewriteExecuteInline(Method* method, u2* insns, 70 MethodType methodType, const InlineSub* inlineSubs); 71static bool rewriteExecuteInlineRange(Method* method, u2* insns, 72 MethodType methodType, const InlineSub* inlineSubs); 73 74 75/* 76 * Return the fd of an open file in the DEX file cache area. If the cache 77 * file doesn't exist or is out of date, this will remove the old entry, 78 * create a new one (writing only the file header), and return with the 79 * "new file" flag set. 80 * 81 * It's possible to execute from an unoptimized DEX file directly, 82 * assuming the byte ordering and structure alignment is correct, but 83 * disadvantageous because some significant optimizations are not possible. 84 * It's not generally possible to do the same from an uncompressed Jar 85 * file entry, because we have to guarantee 32-bit alignment in the 86 * memory-mapped file. 87 * 88 * For a Jar/APK file (a zip archive with "classes.dex" inside), "modWhen" 89 * and "crc32" come from the Zip directory entry. For a stand-alone DEX 90 * file, it's the modification date of the file and the Adler32 from the 91 * DEX header (which immediately follows the magic). If these don't 92 * match what's stored in the opt header, we reject the file immediately. 93 * 94 * On success, the file descriptor will be positioned just past the "opt" 95 * file header, and will be locked with flock. "*pCachedName" will point 96 * to newly-allocated storage. 97 */ 98int dvmOpenCachedDexFile(const char* fileName, const char* cacheFileName, 99 u4 modWhen, u4 crc, bool isBootstrap, bool* pNewFile, bool createIfMissing) 100{ 101 int fd, cc; 102 struct stat fdStat, fileStat; 103 bool readOnly = false; 104 105 *pNewFile = false; 106 107retry: 108 /* 109 * Try to open the cache file. If we've been asked to, 110 * create it if it doesn't exist. 111 */ 112 fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1; 113 if (fd < 0) { 114 fd = open(cacheFileName, O_RDONLY, 0); 115 if (fd < 0) { 116 if (createIfMissing) { 117 LOGE("Can't open dex cache '%s': %s\n", 118 cacheFileName, strerror(errno)); 119 } 120 return fd; 121 } 122 readOnly = true; 123 } 124 125 /* 126 * Grab an exclusive lock on the cache file. If somebody else is 127 * working on it, we'll block here until they complete. Because 128 * we're waiting on an external resource, we go into VMWAIT mode. 129 */ 130 int oldStatus; 131 LOGV("DexOpt: locking cache file %s (fd=%d, boot=%d)\n", 132 cacheFileName, fd, isBootstrap); 133 oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 134 cc = flock(fd, LOCK_EX | LOCK_NB); 135 if (cc != 0) { 136 LOGD("DexOpt: sleeping on flock(%s)\n", cacheFileName); 137 cc = flock(fd, LOCK_EX); 138 } 139 dvmChangeStatus(NULL, oldStatus); 140 if (cc != 0) { 141 LOGE("Can't lock dex cache '%s': %d\n", cacheFileName, cc); 142 close(fd); 143 return -1; 144 } 145 LOGV("DexOpt: locked cache file\n"); 146 147 /* 148 * Check to see if the fd we opened and locked matches the file in 149 * the filesystem. If they don't, then somebody else unlinked ours 150 * and created a new file, and we need to use that one instead. (If 151 * we caught them between the unlink and the create, we'll get an 152 * ENOENT from the file stat.) 153 */ 154 cc = fstat(fd, &fdStat); 155 if (cc != 0) { 156 LOGE("Can't stat open file '%s'\n", cacheFileName); 157 LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName); 158 goto close_fail; 159 } 160 cc = stat(cacheFileName, &fileStat); 161 if (cc != 0 || 162 fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) 163 { 164 LOGD("DexOpt: our open cache file is stale; sleeping and retrying\n"); 165 LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName); 166 flock(fd, LOCK_UN); 167 close(fd); 168 usleep(250 * 1000); /* if something is hosed, don't peg machine */ 169 goto retry; 170 } 171 172 /* 173 * We have the correct file open and locked. If the file size is zero, 174 * then it was just created by us, and we want to fill in some fields 175 * in the "opt" header and set "*pNewFile". Otherwise, we want to 176 * verify that the fields in the header match our expectations, and 177 * reset the file if they don't. 178 */ 179 if (fdStat.st_size == 0) { 180 if (readOnly) { 181 LOGW("DexOpt: file has zero length and isn't writable\n"); 182 goto close_fail; 183 } 184 cc = dexOptCreateEmptyHeader(fd); 185 if (cc != 0) 186 goto close_fail; 187 *pNewFile = true; 188 LOGV("DexOpt: successfully initialized new cache file\n"); 189 } else { 190 bool expectVerify, expectOpt; 191 192 if (gDvm.classVerifyMode == VERIFY_MODE_NONE) 193 expectVerify = false; 194 else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) 195 expectVerify = !isBootstrap; 196 else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ 197 expectVerify = true; 198 199 if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) 200 expectOpt = false; 201 else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED) 202 expectOpt = expectVerify; 203 else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ 204 expectOpt = true; 205 206 LOGV("checking deps, expecting vfy=%d opt=%d\n", 207 expectVerify, expectOpt); 208 209 if (!dvmCheckOptHeaderAndDependencies(fd, true, modWhen, crc, 210 expectVerify, expectOpt)) 211 { 212 if (readOnly) { 213 /* 214 * We could unlink and rewrite the file if we own it or 215 * the "sticky" bit isn't set on the directory. However, 216 * we're not able to truncate it, which spoils things. So, 217 * give up now. 218 */ 219 if (createIfMissing) { 220 LOGW("Cached DEX '%s' (%s) is stale and not writable\n", 221 fileName, cacheFileName); 222 } 223 goto close_fail; 224 } 225 226 /* 227 * If we truncate the existing file before unlinking it, any 228 * process that has it mapped will fail when it tries to touch 229 * the pages. 230 * 231 * This is very important. The zygote process will have the 232 * boot DEX files (core, framework, etc.) mapped early. If 233 * (say) core.dex gets updated, and somebody launches an app 234 * that uses App.dex, then App.dex gets reoptimized because it's 235 * dependent upon the boot classes. However, dexopt will be 236 * using the *new* core.dex to do the optimizations, while the 237 * app will actually be running against the *old* core.dex 238 * because it starts from zygote. 239 * 240 * Even without zygote, it's still possible for a class loader 241 * to pull in an APK that was optimized against an older set 242 * of DEX files. We must ensure that everything fails when a 243 * boot DEX gets updated, and for general "why aren't my 244 * changes doing anything" purposes its best if we just make 245 * everything crash when a DEX they're using gets updated. 246 */ 247 LOGD("Stale deps in cache file; removing and retrying\n"); 248 if (ftruncate(fd, 0) != 0) { 249 LOGW("Warning: unable to truncate cache file '%s': %s\n", 250 cacheFileName, strerror(errno)); 251 /* keep going */ 252 } 253 if (unlink(cacheFileName) != 0) { 254 LOGW("Warning: unable to remove cache file '%s': %d %s\n", 255 cacheFileName, errno, strerror(errno)); 256 /* keep going; permission failure should probably be fatal */ 257 } 258 LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName); 259 flock(fd, LOCK_UN); 260 close(fd); 261 goto retry; 262 } else { 263 LOGV("DexOpt: good deps in cache file\n"); 264 } 265 } 266 267 assert(fd >= 0); 268 return fd; 269 270close_fail: 271 flock(fd, LOCK_UN); 272 close(fd); 273 return -1; 274} 275 276/* 277 * Unlock the file descriptor. 278 * 279 * Returns "true" on success. 280 */ 281bool dvmUnlockCachedDexFile(int fd) 282{ 283 LOGVV("DexOpt: unlocking cache file fd=%d\n", fd); 284 return (flock(fd, LOCK_UN) == 0); 285} 286 287 288/* 289 * Given a descriptor for a file with DEX data in it, produce an 290 * optimized version. 291 * 292 * The file pointed to by "fd" is expected to be a locked shared resource 293 * (or private); we make no efforts to enforce multi-process correctness 294 * here. 295 * 296 * "fileName" is only used for debug output. "modWhen" and "crc" are stored 297 * in the dependency set. 298 * 299 * The "isBootstrap" flag determines how the optimizer and verifier handle 300 * package-scope access checks. When optimizing, we only load the bootstrap 301 * class DEX files and the target DEX, so the flag determines whether the 302 * target DEX classes are given a (synthetic) non-NULL classLoader pointer. 303 * This only really matters if the target DEX contains classes that claim to 304 * be in the same package as bootstrap classes. 305 * 306 * The optimizer will need to load every class in the target DEX file. 307 * This is generally undesirable, so we start a subprocess to do the 308 * work and wait for it to complete. 309 * 310 * Returns "true" on success. All data will have been written to "fd". 311 */ 312bool dvmOptimizeDexFile(int fd, off_t dexOffset, long dexLength, 313 const char* fileName, u4 modWhen, u4 crc, bool isBootstrap) 314{ 315 const char* lastPart = strrchr(fileName, '/'); 316 if (lastPart != NULL) 317 lastPart++; 318 else 319 lastPart = fileName; 320 321 /* 322 * For basic optimizations (byte-swapping and structure aligning) we 323 * don't need to fork(). It looks like fork+exec is causing problems 324 * with gdb on our bewildered Linux distro, so in some situations we 325 * want to avoid this. 326 * 327 * For optimization and/or verification, we need to load all the classes. 328 * 329 * We don't check gDvm.generateRegisterMaps, since that is dependent 330 * upon the verifier state. 331 */ 332 if (gDvm.classVerifyMode == VERIFY_MODE_NONE && 333 (gDvm.dexOptMode == OPTIMIZE_MODE_NONE || 334 gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED)) 335 { 336 LOGD("DexOpt: --- BEGIN (quick) '%s' ---\n", lastPart); 337 return dvmContinueOptimization(fd, dexOffset, dexLength, 338 fileName, modWhen, crc, isBootstrap); 339 } 340 341 342 LOGD("DexOpt: --- BEGIN '%s' (bootstrap=%d) ---\n", lastPart, isBootstrap); 343 344 pid_t pid; 345 346 /* 347 * This could happen if something in our bootclasspath, which we thought 348 * was all optimized, got rejected. 349 */ 350 if (gDvm.optimizing) { 351 LOGW("Rejecting recursive optimization attempt on '%s'\n", fileName); 352 return false; 353 } 354 355 pid = fork(); 356 if (pid == 0) { 357 static const int kUseValgrind = 0; 358 static const char* kDexOptBin = "/bin/dexopt"; 359 static const char* kValgrinder = "/usr/bin/valgrind"; 360 static const int kFixedArgCount = 10; 361 static const int kValgrindArgCount = 5; 362 static const int kMaxIntLen = 12; // '-'+10dig+'\0' -OR- 0x+8dig 363 int bcpSize = dvmGetBootPathSize(); 364 int argc = kFixedArgCount + bcpSize 365 + (kValgrindArgCount * kUseValgrind); 366 char* argv[argc+1]; // last entry is NULL 367 char values[argc][kMaxIntLen]; 368 char* execFile; 369 char* androidRoot; 370 int flags; 371 372 /* change process groups, so we don't clash with ProcessManager */ 373 setpgid(0, 0); 374 375 /* full path to optimizer */ 376 androidRoot = getenv("ANDROID_ROOT"); 377 if (androidRoot == NULL) { 378 LOGW("ANDROID_ROOT not set, defaulting to /system\n"); 379 androidRoot = "/system"; 380 } 381 execFile = malloc(strlen(androidRoot) + strlen(kDexOptBin) + 1); 382 strcpy(execFile, androidRoot); 383 strcat(execFile, kDexOptBin); 384 385 /* 386 * Create arg vector. 387 */ 388 int curArg = 0; 389 390 if (kUseValgrind) { 391 /* probably shouldn't ship the hard-coded path */ 392 argv[curArg++] = (char*)kValgrinder; 393 argv[curArg++] = "--tool=memcheck"; 394 argv[curArg++] = "--leak-check=yes"; // check for leaks too 395 argv[curArg++] = "--leak-resolution=med"; // increase from 2 to 4 396 argv[curArg++] = "--num-callers=16"; // default is 12 397 assert(curArg == kValgrindArgCount); 398 } 399 argv[curArg++] = execFile; 400 401 argv[curArg++] = "--dex"; 402 403 sprintf(values[2], "%d", DALVIK_VM_BUILD); 404 argv[curArg++] = values[2]; 405 406 sprintf(values[3], "%d", fd); 407 argv[curArg++] = values[3]; 408 409 sprintf(values[4], "%d", (int) dexOffset); 410 argv[curArg++] = values[4]; 411 412 sprintf(values[5], "%d", (int) dexLength); 413 argv[curArg++] = values[5]; 414 415 argv[curArg++] = (char*)fileName; 416 417 sprintf(values[7], "%d", (int) modWhen); 418 argv[curArg++] = values[7]; 419 420 sprintf(values[8], "%d", (int) crc); 421 argv[curArg++] = values[8]; 422 423 flags = 0; 424 if (gDvm.dexOptMode != OPTIMIZE_MODE_NONE) { 425 flags |= DEXOPT_OPT_ENABLED; 426 if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL) 427 flags |= DEXOPT_OPT_ALL; 428 } 429 if (gDvm.classVerifyMode != VERIFY_MODE_NONE) { 430 flags |= DEXOPT_VERIFY_ENABLED; 431 if (gDvm.classVerifyMode == VERIFY_MODE_ALL) 432 flags |= DEXOPT_VERIFY_ALL; 433 } 434 if (isBootstrap) 435 flags |= DEXOPT_IS_BOOTSTRAP; 436 if (gDvm.generateRegisterMaps) 437 flags |= DEXOPT_GEN_REGISTER_MAP; 438 sprintf(values[9], "%d", flags); 439 argv[curArg++] = values[9]; 440 441 assert(((!kUseValgrind && curArg == kFixedArgCount) || 442 ((kUseValgrind && curArg == kFixedArgCount+kValgrindArgCount)))); 443 444 ClassPathEntry* cpe; 445 for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 446 argv[curArg++] = cpe->fileName; 447 } 448 assert(curArg == argc); 449 450 argv[curArg] = NULL; 451 452 if (kUseValgrind) 453 execv(kValgrinder, argv); 454 else 455 execv(execFile, argv); 456 457 LOGE("execv '%s'%s failed: %s\n", execFile, 458 kUseValgrind ? " [valgrind]" : "", strerror(errno)); 459 exit(1); 460 } else { 461 LOGV("DexOpt: waiting for verify+opt, pid=%d\n", (int) pid); 462 int status; 463 pid_t gotPid; 464 int oldStatus; 465 466 /* 467 * Wait for the optimization process to finish. We go into VMWAIT 468 * mode here so GC suspension won't have to wait for us. 469 */ 470 oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 471 while (true) { 472 gotPid = waitpid(pid, &status, 0); 473 if (gotPid == -1 && errno == EINTR) { 474 LOGD("waitpid interrupted, retrying\n"); 475 } else { 476 break; 477 } 478 } 479 dvmChangeStatus(NULL, oldStatus); 480 if (gotPid != pid) { 481 LOGE("waitpid failed: wanted %d, got %d: %s\n", 482 (int) pid, (int) gotPid, strerror(errno)); 483 return false; 484 } 485 486 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 487 LOGD("DexOpt: --- END '%s' (success) ---\n", lastPart); 488 return true; 489 } else { 490 LOGW("DexOpt: --- END '%s' --- status=0x%04x, process failed\n", 491 lastPart, status); 492 return false; 493 } 494 } 495} 496 497/* 498 * Do the actual optimization. This is called directly for "minimal" 499 * optimization, or from a newly-created process for "full" optimization. 500 * 501 * For best use of disk/memory, we want to extract once and perform 502 * optimizations in place. If the file has to expand or contract 503 * to match local structure padding/alignment expectations, we want 504 * to do the rewrite as part of the extract, rather than extracting 505 * into a temp file and slurping it back out. (The structure alignment 506 * is currently correct for all platforms, and this isn't expected to 507 * change, so we should be okay with having it already extracted.) 508 * 509 * Returns "true" on success. 510 */ 511bool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength, 512 const char* fileName, u4 modWhen, u4 crc, bool isBootstrap) 513{ 514 DexClassLookup* pClassLookup = NULL; 515 IndexMapSet* pIndexMapSet = NULL; 516 RegisterMapBuilder* pRegMapBuilder = NULL; 517 bool doVerify, doOpt; 518 u4 headerFlags = 0; 519 520 if (gDvm.classVerifyMode == VERIFY_MODE_NONE) 521 doVerify = false; 522 else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) 523 doVerify = !isBootstrap; 524 else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ 525 doVerify = true; 526 527 if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) 528 doOpt = false; 529 else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED) 530 doOpt = doVerify; 531 else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ 532 doOpt = true; 533 534 LOGV("Continuing optimization (%s, isb=%d, vfy=%d, opt=%d)\n", 535 fileName, isBootstrap, doVerify, doOpt); 536 537 assert(dexOffset >= 0); 538 539 /* quick test so we don't blow up on empty file */ 540 if (dexLength < (int) sizeof(DexHeader)) { 541 LOGE("too small to be DEX\n"); 542 return false; 543 } 544 if (dexOffset < (int) sizeof(DexOptHeader)) { 545 LOGE("not enough room for opt header\n"); 546 return false; 547 } 548 549 bool result = false; 550 551 /* 552 * Drop this into a global so we don't have to pass it around. We could 553 * also add a field to DexFile, but since it only pertains to DEX 554 * creation that probably doesn't make sense. 555 */ 556 gDvm.optimizingBootstrapClass = isBootstrap; 557 558 { 559 /* 560 * Map the entire file (so we don't have to worry about page 561 * alignment). The expectation is that the output file contains 562 * our DEX data plus room for a small header. 563 */ 564 bool success; 565 void* mapAddr; 566 mapAddr = mmap(NULL, dexOffset + dexLength, PROT_READ|PROT_WRITE, 567 MAP_SHARED, fd, 0); 568 if (mapAddr == MAP_FAILED) { 569 LOGE("unable to mmap DEX cache: %s\n", strerror(errno)); 570 goto bail; 571 } 572 573 /* 574 * Rewrite the file. Byte reordering, structure realigning, 575 * class verification, and bytecode optimization are all performed 576 * here. 577 * 578 * In theory the file could change size and bits could shift around. 579 * In practice this would be annoying to deal with, so the file 580 * layout is designed so that it can always be rewritten in place. 581 * 582 * This sets "headerFlags" and creates the class lookup table as 583 * part of doing the processing. 584 */ 585 success = rewriteDex(((u1*) mapAddr) + dexOffset, dexLength, 586 doVerify, doOpt, &headerFlags, &pClassLookup); 587 588 if (success) { 589 DvmDex* pDvmDex = NULL; 590 u1* dexAddr = ((u1*) mapAddr) + dexOffset; 591 592 if (dvmDexFileOpenPartial(dexAddr, dexLength, &pDvmDex) != 0) { 593 LOGE("Unable to create DexFile\n"); 594 success = false; 595 } else { 596 /* 597 * If configured to do so, scan the instructions, looking 598 * for ways to reduce the size of the resolved-constant table. 599 * This is done post-optimization, across the instructions 600 * in all methods in all classes (even the ones that failed 601 * to load). 602 */ 603 pIndexMapSet = dvmRewriteConstants(pDvmDex); 604 605 /* 606 * If configured to do so, generate a full set of register 607 * maps for all verified classes. 608 */ 609 if (gDvm.generateRegisterMaps) { 610 pRegMapBuilder = dvmGenerateRegisterMaps(pDvmDex); 611 if (pRegMapBuilder == NULL) { 612 LOGE("Failed generating register maps\n"); 613 success = false; 614 } 615 } 616 617 DexHeader* pHeader = (DexHeader*)pDvmDex->pHeader; 618 updateChecksum(dexAddr, dexLength, pHeader); 619 620 dvmDexFileFree(pDvmDex); 621 } 622 } 623 624 /* unmap the read-write version, forcing writes to disk */ 625 if (msync(mapAddr, dexOffset + dexLength, MS_SYNC) != 0) { 626 LOGW("msync failed: %s\n", strerror(errno)); 627 // weird, but keep going 628 } 629#if 1 630 /* 631 * This causes clean shutdown to fail, because we have loaded classes 632 * that point into it. For the optimizer this isn't a problem, 633 * because it's more efficient for the process to simply exit. 634 * Exclude this code when doing clean shutdown for valgrind. 635 */ 636 if (munmap(mapAddr, dexOffset + dexLength) != 0) { 637 LOGE("munmap failed: %s\n", strerror(errno)); 638 goto bail; 639 } 640#endif 641 642 if (!success) 643 goto bail; 644 } 645 646 /* get start offset, and adjust deps start for 64-bit alignment */ 647 off_t depsOffset, auxOffset, endOffset, adjOffset; 648 int depsLength, auxLength; 649 u4 optChecksum; 650 651 depsOffset = lseek(fd, 0, SEEK_END); 652 if (depsOffset < 0) { 653 LOGE("lseek to EOF failed: %s\n", strerror(errno)); 654 goto bail; 655 } 656 adjOffset = (depsOffset + 7) & ~(0x07); 657 if (adjOffset != depsOffset) { 658 LOGV("Adjusting deps start from %d to %d\n", 659 (int) depsOffset, (int) adjOffset); 660 depsOffset = adjOffset; 661 lseek(fd, depsOffset, SEEK_SET); 662 } 663 664 /* 665 * Append the dependency list. 666 */ 667 if (writeDependencies(fd, modWhen, crc) != 0) { 668 LOGW("Failed writing dependencies\n"); 669 goto bail; 670 } 671 672 /* compute deps length, then adjust aux start for 64-bit alignment */ 673 auxOffset = lseek(fd, 0, SEEK_END); 674 depsLength = auxOffset - depsOffset; 675 676 adjOffset = (auxOffset + 7) & ~(0x07); 677 if (adjOffset != auxOffset) { 678 LOGV("Adjusting aux start from %d to %d\n", 679 (int) auxOffset, (int) adjOffset); 680 auxOffset = adjOffset; 681 lseek(fd, auxOffset, SEEK_SET); 682 } 683 684 /* 685 * Append any auxillary pre-computed data structures. 686 */ 687 if (!writeAuxData(fd, pClassLookup, pIndexMapSet, pRegMapBuilder)) { 688 LOGW("Failed writing aux data\n"); 689 goto bail; 690 } 691 692 endOffset = lseek(fd, 0, SEEK_END); 693 auxLength = endOffset - auxOffset; 694 695 /* compute checksum from start of deps to end of aux area */ 696 if (!computeFileChecksum(fd, depsOffset, 697 (auxOffset+auxLength) - depsOffset, &optChecksum)) 698 { 699 goto bail; 700 } 701 702 /* 703 * Output the "opt" header with all values filled in and a correct 704 * magic number. 705 */ 706 DexOptHeader optHdr; 707 memset(&optHdr, 0xff, sizeof(optHdr)); 708 memcpy(optHdr.magic, DEX_OPT_MAGIC, 4); 709 memcpy(optHdr.magic+4, DEX_OPT_MAGIC_VERS, 4); 710 optHdr.dexOffset = (u4) dexOffset; 711 optHdr.dexLength = (u4) dexLength; 712 optHdr.depsOffset = (u4) depsOffset; 713 optHdr.depsLength = (u4) depsLength; 714 optHdr.auxOffset = (u4) auxOffset; 715 optHdr.auxLength = (u4) auxLength; 716 717 optHdr.flags = headerFlags; 718 optHdr.checksum = optChecksum; 719 720 ssize_t actual; 721 lseek(fd, 0, SEEK_SET); 722 actual = write(fd, &optHdr, sizeof(optHdr)); 723 if (actual != sizeof(optHdr)) { 724 logFailedWrite(sizeof(optHdr), actual, "opt header", errno); 725 goto bail; 726 } 727 728 LOGV("Successfully wrote DEX header\n"); 729 result = true; 730 731 //dvmRegisterMapDumpStats(); 732 733bail: 734 dvmFreeIndexMapSet(pIndexMapSet); 735 dvmFreeRegisterMapBuilder(pRegMapBuilder); 736 free(pClassLookup); 737 return result; 738} 739 740 741/* 742 * Get the cache file name from a ClassPathEntry. 743 */ 744static const char* getCacheFileName(const ClassPathEntry* cpe) 745{ 746 switch (cpe->kind) { 747 case kCpeJar: 748 return dvmGetJarFileCacheFileName((JarFile*) cpe->ptr); 749 case kCpeDex: 750 return dvmGetRawDexFileCacheFileName((RawDexFile*) cpe->ptr); 751 default: 752 LOGE("DexOpt: unexpected cpe kind %d\n", cpe->kind); 753 dvmAbort(); 754 return NULL; 755 } 756} 757 758/* 759 * Get the SHA-1 signature. 760 */ 761static const u1* getSignature(const ClassPathEntry* cpe) 762{ 763 DvmDex* pDvmDex; 764 765 switch (cpe->kind) { 766 case kCpeJar: 767 pDvmDex = dvmGetJarFileDex((JarFile*) cpe->ptr); 768 break; 769 case kCpeDex: 770 pDvmDex = dvmGetRawDexFileDex((RawDexFile*) cpe->ptr); 771 break; 772 default: 773 LOGE("unexpected cpe kind %d\n", cpe->kind); 774 dvmAbort(); 775 pDvmDex = NULL; // make gcc happy 776 } 777 778 assert(pDvmDex != NULL); 779 return pDvmDex->pDexFile->pHeader->signature; 780} 781 782 783/* 784 * Dependency layout: 785 * 4b Source file modification time, in seconds since 1970 UTC 786 * 4b CRC-32 from Zip entry, or Adler32 from source DEX header 787 * 4b Dalvik VM build number 788 * 4b Number of dependency entries that follow 789 * Dependency entries: 790 * 4b Name length (including terminating null) 791 * var Full path of cache entry (null terminated) 792 * 20b SHA-1 signature from source DEX file 793 * 794 * If this changes, update DEX_OPT_MAGIC_VERS. 795 */ 796static const size_t kMinDepSize = 4 * 4; 797static const size_t kMaxDepSize = 4 * 4 + 1024; // sanity check 798 799/* 800 * Read the "opt" header, verify it, then read the dependencies section 801 * and verify that data as well. 802 * 803 * If "sourceAvail" is "true", this will verify that "modWhen" and "crc" 804 * match up with what is stored in the header. If they don't, we reject 805 * the file so that it can be recreated from the updated original. If 806 * "sourceAvail" isn't set, e.g. for a .odex file, we ignore these arguments. 807 * 808 * On successful return, the file will be seeked immediately past the 809 * "opt" header. 810 */ 811bool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen, 812 u4 crc, bool expectVerify, bool expectOpt) 813{ 814 DexOptHeader optHdr; 815 u1* depData = NULL; 816 const u1* magic; 817 off_t posn; 818 int result = false; 819 ssize_t actual; 820 821 /* 822 * Start at the start. The "opt" header, when present, will always be 823 * the first thing in the file. 824 */ 825 if (lseek(fd, 0, SEEK_SET) != 0) { 826 LOGE("DexOpt: failed to seek to start of file: %s\n", strerror(errno)); 827 goto bail; 828 } 829 830 /* 831 * Read and do trivial verification on the opt header. The header is 832 * always in host byte order. 833 */ 834 if (read(fd, &optHdr, sizeof(optHdr)) != sizeof(optHdr)) { 835 LOGE("DexOpt: failed reading opt header: %s\n", strerror(errno)); 836 goto bail; 837 } 838 839 magic = optHdr.magic; 840 if (memcmp(magic, DEX_OPT_MAGIC, 4) != 0) { 841 /* not a DEX file, or previous attempt was interrupted */ 842 LOGD("DexOpt: incorrect opt magic number (0x%02x %02x %02x %02x)\n", 843 magic[0], magic[1], magic[2], magic[3]); 844 goto bail; 845 } 846 if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) { 847 LOGW("DexOpt: stale opt version (0x%02x %02x %02x %02x)\n", 848 magic[4], magic[5], magic[6], magic[7]); 849 goto bail; 850 } 851 if (optHdr.depsLength < kMinDepSize || optHdr.depsLength > kMaxDepSize) { 852 LOGW("DexOpt: weird deps length %d, bailing\n", optHdr.depsLength); 853 goto bail; 854 } 855 856 /* 857 * Do the header flags match up with what we want? 858 * 859 * This is useful because it allows us to automatically regenerate 860 * a file when settings change (e.g. verification is now mandatory), 861 * but can cause difficulties if the bootstrap classes we depend upon 862 * were handled differently than the current options specify. We get 863 * upset because they're not verified or optimized, but we're not able 864 * to regenerate them because the installer won't let us. 865 * 866 * (This is also of limited value when !sourceAvail.) 867 * 868 * So, for now, we essentially ignore "expectVerify" and "expectOpt" 869 * by limiting the match mask. 870 * 871 * The only thing we really can't handle is incorrect byte-ordering. 872 */ 873 const u4 matchMask = DEX_OPT_FLAG_BIG; 874 u4 expectedFlags = 0; 875#if __BYTE_ORDER != __LITTLE_ENDIAN 876 expectedFlags |= DEX_OPT_FLAG_BIG; 877#endif 878 if (expectVerify) 879 expectedFlags |= DEX_FLAG_VERIFIED; 880 if (expectOpt) 881 expectedFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS; 882 if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) { 883 LOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)\n", 884 expectedFlags, optHdr.flags, matchMask); 885 goto bail; 886 } 887 888 posn = lseek(fd, optHdr.depsOffset, SEEK_SET); 889 if (posn < 0) { 890 LOGW("DexOpt: seek to deps failed: %s\n", strerror(errno)); 891 goto bail; 892 } 893 894 /* 895 * Read all of the dependency stuff into memory. 896 */ 897 depData = (u1*) malloc(optHdr.depsLength); 898 if (depData == NULL) { 899 LOGW("DexOpt: unable to allocate %d bytes for deps\n", 900 optHdr.depsLength); 901 goto bail; 902 } 903 actual = read(fd, depData, optHdr.depsLength); 904 if (actual != (ssize_t) optHdr.depsLength) { 905 LOGW("DexOpt: failed reading deps: %d of %d (err=%s)\n", 906 (int) actual, optHdr.depsLength, strerror(errno)); 907 goto bail; 908 } 909 910 /* 911 * Verify simple items. 912 */ 913 const u1* ptr; 914 u4 val; 915 916 ptr = depData; 917 val = read4LE(&ptr); 918 if (sourceAvail && val != modWhen) { 919 LOGI("DexOpt: source file mod time mismatch (%08x vs %08x)\n", 920 val, modWhen); 921 goto bail; 922 } 923 val = read4LE(&ptr); 924 if (sourceAvail && val != crc) { 925 LOGI("DexOpt: source file CRC mismatch (%08x vs %08x)\n", val, crc); 926 goto bail; 927 } 928 val = read4LE(&ptr); 929 if (val != DALVIK_VM_BUILD) { 930 LOGD("DexOpt: VM build version mismatch (%d vs %d)\n", 931 val, DALVIK_VM_BUILD); 932 goto bail; 933 } 934 935 /* 936 * Verify dependencies on other cached DEX files. It must match 937 * exactly with what is currently defined in the bootclasspath. 938 */ 939 ClassPathEntry* cpe; 940 u4 numDeps; 941 942 numDeps = read4LE(&ptr); 943 LOGV("+++ DexOpt: numDeps = %d\n", numDeps); 944 for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 945 const char* cacheFileName = getCacheFileName(cpe); 946 const u1* signature = getSignature(cpe); 947 size_t len = strlen(cacheFileName) +1; 948 u4 storedStrLen; 949 950 if (numDeps == 0) { 951 /* more entries in bootclasspath than in deps list */ 952 LOGI("DexOpt: not all deps represented\n"); 953 goto bail; 954 } 955 956 storedStrLen = read4LE(&ptr); 957 if (len != storedStrLen || 958 strcmp(cacheFileName, (const char*) ptr) != 0) 959 { 960 LOGI("DexOpt: mismatch dep name: '%s' vs. '%s'\n", 961 cacheFileName, ptr); 962 goto bail; 963 } 964 965 ptr += storedStrLen; 966 967 if (memcmp(signature, ptr, kSHA1DigestLen) != 0) { 968 LOGI("DexOpt: mismatch dep signature for '%s'\n", cacheFileName); 969 goto bail; 970 } 971 ptr += kSHA1DigestLen; 972 973 LOGV("DexOpt: dep match on '%s'\n", cacheFileName); 974 975 numDeps--; 976 } 977 978 if (numDeps != 0) { 979 /* more entries in deps list than in classpath */ 980 LOGI("DexOpt: Some deps went away\n"); 981 goto bail; 982 } 983 984 // consumed all data and no more? 985 if (ptr != depData + optHdr.depsLength) { 986 LOGW("DexOpt: Spurious dep data? %d vs %d\n", 987 (int) (ptr - depData), optHdr.depsLength); 988 assert(false); 989 } 990 991 result = true; 992 993bail: 994 free(depData); 995 return result; 996} 997 998/* 999 * Write the dependency info to "fd" at the current file position. 1000 */ 1001static int writeDependencies(int fd, u4 modWhen, u4 crc) 1002{ 1003 u1* buf = NULL; 1004 ssize_t actual; 1005 int result = -1; 1006 ssize_t bufLen; 1007 ClassPathEntry* cpe; 1008 int i, numDeps; 1009 1010 /* 1011 * Count up the number of completed entries in the bootclasspath. 1012 */ 1013 numDeps = 0; 1014 bufLen = 0; 1015 for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 1016 const char* cacheFileName = getCacheFileName(cpe); 1017 LOGV("+++ DexOpt: found dep '%s'\n", cacheFileName); 1018 1019 numDeps++; 1020 bufLen += strlen(cacheFileName) +1; 1021 } 1022 1023 bufLen += 4*4 + numDeps * (4+kSHA1DigestLen); 1024 1025 buf = malloc(bufLen); 1026 1027 set4LE(buf+0, modWhen); 1028 set4LE(buf+4, crc); 1029 set4LE(buf+8, DALVIK_VM_BUILD); 1030 set4LE(buf+12, numDeps); 1031 1032 // TODO: do we want to add dvmGetInlineOpsTableLength() here? Won't 1033 // help us if somebody replaces an existing entry, but it'd catch 1034 // additions/removals. 1035 1036 u1* ptr = buf + 4*4; 1037 for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 1038 const char* cacheFileName = getCacheFileName(cpe); 1039 const u1* signature = getSignature(cpe); 1040 int len = strlen(cacheFileName) +1; 1041 1042 if (ptr + 4 + len + kSHA1DigestLen > buf + bufLen) { 1043 LOGE("DexOpt: overran buffer\n"); 1044 dvmAbort(); 1045 } 1046 1047 set4LE(ptr, len); 1048 ptr += 4; 1049 memcpy(ptr, cacheFileName, len); 1050 ptr += len; 1051 memcpy(ptr, signature, kSHA1DigestLen); 1052 ptr += kSHA1DigestLen; 1053 } 1054 1055 assert(ptr == buf + bufLen); 1056 1057 actual = write(fd, buf, bufLen); 1058 if (actual != bufLen) { 1059 result = (errno != 0) ? errno : -1; 1060 logFailedWrite(bufLen, actual, "dep info", errno); 1061 } else { 1062 result = 0; 1063 } 1064 1065 free(buf); 1066 return result; 1067} 1068 1069 1070/* 1071 * Write a block of data in "chunk" format. 1072 * 1073 * The chunk header fields are always in "native" byte order. If "size" 1074 * is not a multiple of 8 bytes, the data area is padded out. 1075 */ 1076static bool writeChunk(int fd, u4 type, const void* data, size_t size) 1077{ 1078 ssize_t actual; 1079 union { /* save a syscall by grouping these together */ 1080 char raw[8]; 1081 struct { 1082 u4 type; 1083 u4 size; 1084 } ts; 1085 } header; 1086 1087 assert(sizeof(header) == 8); 1088 1089 LOGV("Writing chunk, type=%.4s size=%d\n", (char*) &type, size); 1090 1091 header.ts.type = type; 1092 header.ts.size = (u4) size; 1093 actual = write(fd, &header, sizeof(header)); 1094 if (actual != sizeof(header)) { 1095 logFailedWrite(size, actual, "aux chunk header write", errno); 1096 return false; 1097 } 1098 1099 if (size > 0) { 1100 actual = write(fd, data, size); 1101 if (actual != (ssize_t) size) { 1102 logFailedWrite(size, actual, "aux chunk write", errno); 1103 return false; 1104 } 1105 } 1106 1107 /* if necessary, pad to 64-bit alignment */ 1108 if ((size & 7) != 0) { 1109 int padSize = 8 - (size & 7); 1110 LOGV("size was %d, inserting %d pad bytes\n", size, padSize); 1111 lseek(fd, padSize, SEEK_CUR); 1112 } 1113 1114 assert( ((int)lseek(fd, 0, SEEK_CUR) & 7) == 0); 1115 1116 return true; 1117} 1118 1119/* 1120 * Write aux data. 1121 * 1122 * We have different pieces, some of which may be optional. To make the 1123 * most effective use of space, we use a "chunk" format, with a 4-byte 1124 * type and a 4-byte length. We guarantee 64-bit alignment for the data, 1125 * so it can be used directly when the file is mapped for reading. 1126 */ 1127static bool writeAuxData(int fd, const DexClassLookup* pClassLookup, 1128 const IndexMapSet* pIndexMapSet, const RegisterMapBuilder* pRegMapBuilder) 1129{ 1130 /* pre-computed class lookup hash table */ 1131 if (!writeChunk(fd, (u4) kDexChunkClassLookup, 1132 pClassLookup, pClassLookup->size)) 1133 { 1134 return false; 1135 } 1136 1137 /* remapped constants (optional) */ 1138 if (pIndexMapSet != NULL) { 1139 if (!writeChunk(fd, pIndexMapSet->chunkType, 1140 pIndexMapSet->chunkData, pIndexMapSet->chunkDataLen)) 1141 { 1142 return false; 1143 } 1144 } 1145 1146 /* register maps (optional) */ 1147 if (pRegMapBuilder != NULL) { 1148 if (!writeChunk(fd, (u4) kDexChunkRegisterMaps, 1149 pRegMapBuilder->data, pRegMapBuilder->size)) 1150 { 1151 return false; 1152 } 1153 } 1154 1155 /* write the end marker */ 1156 if (!writeChunk(fd, (u4) kDexChunkEnd, NULL, 0)) { 1157 return false; 1158 } 1159 1160 return true; 1161} 1162 1163/* 1164 * Log a failed write. 1165 */ 1166static void logFailedWrite(size_t expected, ssize_t actual, const char* msg, 1167 int err) 1168{ 1169 LOGE("Write failed: %s (%d of %d): %s\n", 1170 msg, (int)actual, (int)expected, strerror(err)); 1171} 1172 1173/* 1174 * Compute a checksum on a piece of an open file. 1175 * 1176 * File will be positioned at end of checksummed area. 1177 * 1178 * Returns "true" on success. 1179 */ 1180static bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum) 1181{ 1182 unsigned char readBuf[8192]; 1183 ssize_t actual; 1184 uLong adler; 1185 1186 if (lseek(fd, start, SEEK_SET) != start) { 1187 LOGE("Unable to seek to start of checksum area (%ld): %s\n", 1188 (long) start, strerror(errno)); 1189 return false; 1190 } 1191 1192 adler = adler32(0L, Z_NULL, 0); 1193 1194 while (length != 0) { 1195 size_t wanted = (length < sizeof(readBuf)) ? length : sizeof(readBuf); 1196 actual = read(fd, readBuf, wanted); 1197 if (actual <= 0) { 1198 LOGE("Read failed (%d) while computing checksum (len=%zu): %s\n", 1199 (int) actual, length, strerror(errno)); 1200 return false; 1201 } 1202 1203 adler = adler32(adler, readBuf, actual); 1204 1205 length -= actual; 1206 } 1207 1208 *pSum = adler; 1209 return true; 1210} 1211 1212 1213/* 1214 * =========================================================================== 1215 * Optimizations 1216 * =========================================================================== 1217 */ 1218 1219/* 1220 * Perform in-place rewrites on a memory-mapped DEX file. 1221 * 1222 * This happens in a short-lived child process, so we can go nutty with 1223 * loading classes and allocating memory. 1224 */ 1225static bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt, 1226 u4* pHeaderFlags, DexClassLookup** ppClassLookup) 1227{ 1228 u8 prepWhen, loadWhen, verifyWhen, optWhen; 1229 DvmDex* pDvmDex = NULL; 1230 bool result = false; 1231 1232 *pHeaderFlags = 0; 1233 1234 LOGV("+++ swapping bytes\n"); 1235 if (dexFixByteOrdering(addr, len) != 0) 1236 goto bail; 1237#if __BYTE_ORDER != __LITTLE_ENDIAN 1238 *pHeaderFlags |= DEX_OPT_FLAG_BIG; 1239#endif 1240 1241 /* 1242 * Now that the DEX file can be read directly, create a DexFile for it. 1243 */ 1244 if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) { 1245 LOGE("Unable to create DexFile\n"); 1246 goto bail; 1247 } 1248 1249 /* 1250 * Create the class lookup table. 1251 */ 1252 //startWhen = dvmGetRelativeTimeUsec(); 1253 *ppClassLookup = dexCreateClassLookup(pDvmDex->pDexFile); 1254 if (*ppClassLookup == NULL) 1255 goto bail; 1256 1257 /* 1258 * Bail out early if they don't want The Works. The current implementation 1259 * doesn't fork a new process if this flag isn't set, so we really don't 1260 * want to continue on with the crazy class loading. 1261 */ 1262 if (!doVerify && !doOpt) { 1263 result = true; 1264 goto bail; 1265 } 1266 1267 /* this is needed for the next part */ 1268 pDvmDex->pDexFile->pClassLookup = *ppClassLookup; 1269 1270 prepWhen = dvmGetRelativeTimeUsec(); 1271 1272 /* 1273 * Load all classes found in this DEX file. If they fail to load for 1274 * some reason, they won't get verified (which is as it should be). 1275 */ 1276 if (!loadAllClasses(pDvmDex)) 1277 goto bail; 1278 loadWhen = dvmGetRelativeTimeUsec(); 1279 1280 /* 1281 * Verify all classes in the DEX file. Export the "is verified" flag 1282 * to the DEX file we're creating. 1283 */ 1284 if (doVerify) { 1285 dvmVerifyAllClasses(pDvmDex->pDexFile); 1286 *pHeaderFlags |= DEX_FLAG_VERIFIED; 1287 } 1288 verifyWhen = dvmGetRelativeTimeUsec(); 1289 1290 /* 1291 * Optimize the classes we successfully loaded. If the opt mode is 1292 * OPTIMIZE_MODE_VERIFIED, each class must have been successfully 1293 * verified or we'll skip it. 1294 */ 1295#ifndef PROFILE_FIELD_ACCESS 1296 if (doOpt) { 1297 optimizeLoadedClasses(pDvmDex->pDexFile); 1298 *pHeaderFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS; 1299 } 1300#endif 1301 optWhen = dvmGetRelativeTimeUsec(); 1302 1303 LOGD("DexOpt: load %dms, verify %dms, opt %dms\n", 1304 (int) (loadWhen - prepWhen) / 1000, 1305 (int) (verifyWhen - loadWhen) / 1000, 1306 (int) (optWhen - verifyWhen) / 1000); 1307 1308 result = true; 1309 1310bail: 1311 /* free up storage */ 1312 dvmDexFileFree(pDvmDex); 1313 1314 return result; 1315} 1316 1317/* 1318 * Update the Adler-32 checksum stored in the DEX file. This covers the 1319 * swapped and optimized DEX data, but does not include the opt header 1320 * or auxillary data. 1321 */ 1322static void updateChecksum(u1* addr, int len, DexHeader* pHeader) 1323{ 1324 /* 1325 * Rewrite the checksum. We leave the SHA-1 signature alone. 1326 */ 1327 uLong adler = adler32(0L, Z_NULL, 0); 1328 const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum); 1329 1330 adler = adler32(adler, addr + nonSum, len - nonSum); 1331 pHeader->checksum = adler; 1332} 1333 1334/* 1335 * Try to load all classes in the specified DEX. If they have some sort 1336 * of broken dependency, e.g. their superclass lives in a different DEX 1337 * that wasn't previously loaded into the bootstrap class path, loading 1338 * will fail. This is the desired behavior. 1339 * 1340 * We have no notion of class loader at this point, so we load all of 1341 * the classes with the bootstrap class loader. It turns out this has 1342 * exactly the behavior we want, and has no ill side effects because we're 1343 * running in a separate process and anything we load here will be forgotten. 1344 * 1345 * We set the CLASS_MULTIPLE_DEFS flag here if we see multiple definitions. 1346 * This works because we only call here as part of optimization / pre-verify, 1347 * not during verification as part of loading a class into a running VM. 1348 * 1349 * This returns "false" if the world is too screwed up to do anything 1350 * useful at all. 1351 */ 1352static bool loadAllClasses(DvmDex* pDvmDex) 1353{ 1354 u4 count = pDvmDex->pDexFile->pHeader->classDefsSize; 1355 u4 idx; 1356 int loaded = 0; 1357 1358 LOGV("DexOpt: +++ trying to load %d classes\n", count); 1359 1360 dvmSetBootPathExtraDex(pDvmDex); 1361 1362 /* 1363 * We have some circularity issues with Class and Object that are most 1364 * easily avoided by ensuring that Object is never the first thing we 1365 * try to find. Take care of that here. (We only need to do this when 1366 * loading classes from the DEX file that contains Object, and only 1367 * when Object comes first in the list, but it costs very little to 1368 * do it in all cases.) 1369 */ 1370 if (dvmFindSystemClass("Ljava/lang/Class;") == NULL) { 1371 LOGE("ERROR: java.lang.Class does not exist!\n"); 1372 return false; 1373 } 1374 1375 for (idx = 0; idx < count; idx++) { 1376 const DexClassDef* pClassDef; 1377 const char* classDescriptor; 1378 ClassObject* newClass; 1379 1380 pClassDef = dexGetClassDef(pDvmDex->pDexFile, idx); 1381 classDescriptor = 1382 dexStringByTypeIdx(pDvmDex->pDexFile, pClassDef->classIdx); 1383 1384 LOGV("+++ loading '%s'", classDescriptor); 1385 //newClass = dvmDefineClass(pDexFile, classDescriptor, 1386 // NULL); 1387 newClass = dvmFindSystemClassNoInit(classDescriptor); 1388 if (newClass == NULL) { 1389 LOGV("DexOpt: failed loading '%s'\n", classDescriptor); 1390 dvmClearOptException(dvmThreadSelf()); 1391 } else if (newClass->pDvmDex != pDvmDex) { 1392 /* 1393 * We don't load the new one, and we tag the first one found 1394 * with the "multiple def" flag so the resolver doesn't try 1395 * to make it available. 1396 */ 1397 LOGD("DexOpt: '%s' has an earlier definition; blocking out\n", 1398 classDescriptor); 1399 SET_CLASS_FLAG(newClass, CLASS_MULTIPLE_DEFS); 1400 } else { 1401 loaded++; 1402 } 1403 } 1404 LOGV("DexOpt: +++ successfully loaded %d classes\n", loaded); 1405 1406 dvmSetBootPathExtraDex(NULL); 1407 return true; 1408} 1409 1410 1411/* 1412 * Create a table of inline substitutions. 1413 * 1414 * TODO: this is currently just a linear array. We will want to put this 1415 * into a hash table as the list size increases. 1416 */ 1417static InlineSub* createInlineSubsTable(void) 1418{ 1419 const InlineOperation* ops = dvmGetInlineOpsTable(); 1420 const int count = dvmGetInlineOpsTableLength(); 1421 InlineSub* table; 1422 Method* method; 1423 ClassObject* clazz; 1424 int i, tableIndex; 1425 1426 /* 1427 * Allocate for optimism: one slot per entry, plus an end-of-list marker. 1428 */ 1429 table = malloc(sizeof(InlineSub) * (count+1)); 1430 1431 tableIndex = 0; 1432 for (i = 0; i < count; i++) { 1433 clazz = dvmFindClassNoInit(ops[i].classDescriptor, NULL); 1434 if (clazz == NULL) { 1435 LOGV("DexOpt: can't inline for class '%s': not found\n", 1436 ops[i].classDescriptor); 1437 dvmClearOptException(dvmThreadSelf()); 1438 } else { 1439 /* 1440 * Method could be virtual or direct. Try both. Don't use 1441 * the "hier" versions. 1442 */ 1443 method = dvmFindDirectMethodByDescriptor(clazz, ops[i].methodName, 1444 ops[i].methodSignature); 1445 if (method == NULL) 1446 method = dvmFindVirtualMethodByDescriptor(clazz, ops[i].methodName, 1447 ops[i].methodSignature); 1448 if (method == NULL) { 1449 LOGW("DexOpt: can't inline %s.%s %s: method not found\n", 1450 ops[i].classDescriptor, ops[i].methodName, 1451 ops[i].methodSignature); 1452 } else { 1453 if (!dvmIsFinalClass(clazz) && !dvmIsFinalMethod(method)) { 1454 LOGW("DexOpt: WARNING: inline op on non-final class/method " 1455 "%s.%s\n", 1456 clazz->descriptor, method->name); 1457 /* fail? */ 1458 } 1459 if (dvmIsSynchronizedMethod(method) || 1460 dvmIsDeclaredSynchronizedMethod(method)) 1461 { 1462 LOGW("DexOpt: WARNING: inline op on synchronized method " 1463 "%s.%s\n", 1464 clazz->descriptor, method->name); 1465 /* fail? */ 1466 } 1467 1468 table[tableIndex].method = method; 1469 table[tableIndex].inlineIdx = i; 1470 tableIndex++; 1471 1472 LOGV("DexOpt: will inline %d: %s.%s %s\n", i, 1473 ops[i].classDescriptor, ops[i].methodName, 1474 ops[i].methodSignature); 1475 } 1476 } 1477 } 1478 1479 /* mark end of table */ 1480 table[tableIndex].method = NULL; 1481 LOGV("DexOpt: inline table has %d entries\n", tableIndex); 1482 1483 return table; 1484} 1485 1486/* 1487 * Run through all classes that were successfully loaded from this DEX 1488 * file and optimize their code sections. 1489 */ 1490static void optimizeLoadedClasses(DexFile* pDexFile) 1491{ 1492 u4 count = pDexFile->pHeader->classDefsSize; 1493 u4 idx; 1494 InlineSub* inlineSubs = NULL; 1495 1496 LOGV("DexOpt: +++ optimizing up to %d classes\n", count); 1497 assert(gDvm.dexOptMode != OPTIMIZE_MODE_NONE); 1498 1499 inlineSubs = createInlineSubsTable(); 1500 1501 for (idx = 0; idx < count; idx++) { 1502 const DexClassDef* pClassDef; 1503 const char* classDescriptor; 1504 ClassObject* clazz; 1505 1506 pClassDef = dexGetClassDef(pDexFile, idx); 1507 classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); 1508 1509 /* all classes are loaded into the bootstrap class loader */ 1510 clazz = dvmLookupClass(classDescriptor, NULL, false); 1511 if (clazz != NULL) { 1512 if ((pClassDef->accessFlags & CLASS_ISPREVERIFIED) == 0 && 1513 gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED) 1514 { 1515 LOGV("DexOpt: not optimizing '%s': not verified\n", 1516 classDescriptor); 1517 } else if (clazz->pDvmDex->pDexFile != pDexFile) { 1518 /* shouldn't be here -- verifier should have caught */ 1519 LOGD("DexOpt: not optimizing '%s': multiple definitions\n", 1520 classDescriptor); 1521 } else { 1522 optimizeClass(clazz, inlineSubs); 1523 1524 /* set the flag whether or not we actually did anything */ 1525 ((DexClassDef*)pClassDef)->accessFlags |= 1526 CLASS_ISOPTIMIZED; 1527 } 1528 } else { 1529 LOGV("DexOpt: not optimizing unavailable class '%s'\n", 1530 classDescriptor); 1531 } 1532 } 1533 1534 free(inlineSubs); 1535} 1536 1537/* 1538 * Optimize the specified class. 1539 */ 1540static void optimizeClass(ClassObject* clazz, const InlineSub* inlineSubs) 1541{ 1542 int i; 1543 1544 for (i = 0; i < clazz->directMethodCount; i++) { 1545 if (!optimizeMethod(&clazz->directMethods[i], inlineSubs)) 1546 goto fail; 1547 } 1548 for (i = 0; i < clazz->virtualMethodCount; i++) { 1549 if (!optimizeMethod(&clazz->virtualMethods[i], inlineSubs)) 1550 goto fail; 1551 } 1552 1553 return; 1554 1555fail: 1556 LOGV("DexOpt: ceasing optimization attempts on %s\n", clazz->descriptor); 1557} 1558 1559/* 1560 * Optimize instructions in a method. 1561 * 1562 * Returns "true" if all went well, "false" if we bailed out early when 1563 * something failed. 1564 */ 1565static bool optimizeMethod(Method* method, const InlineSub* inlineSubs) 1566{ 1567 u4 insnsSize; 1568 u2* insns; 1569 u2 inst; 1570 1571 if (dvmIsNativeMethod(method) || dvmIsAbstractMethod(method)) 1572 return true; 1573 1574 insns = (u2*) method->insns; 1575 assert(insns != NULL); 1576 insnsSize = dvmGetMethodInsnsSize(method); 1577 1578 while (insnsSize > 0) { 1579 int width; 1580 1581 inst = *insns & 0xff; 1582 1583 switch (inst) { 1584 case OP_IGET: 1585 case OP_IGET_BOOLEAN: 1586 case OP_IGET_BYTE: 1587 case OP_IGET_CHAR: 1588 case OP_IGET_SHORT: 1589 rewriteInstField(method, insns, OP_IGET_QUICK); 1590 break; 1591 case OP_IGET_WIDE: 1592 rewriteInstField(method, insns, OP_IGET_WIDE_QUICK); 1593 break; 1594 case OP_IGET_OBJECT: 1595 rewriteInstField(method, insns, OP_IGET_OBJECT_QUICK); 1596 break; 1597 case OP_IPUT: 1598 case OP_IPUT_BOOLEAN: 1599 case OP_IPUT_BYTE: 1600 case OP_IPUT_CHAR: 1601 case OP_IPUT_SHORT: 1602 rewriteInstField(method, insns, OP_IPUT_QUICK); 1603 break; 1604 case OP_IPUT_WIDE: 1605 rewriteInstField(method, insns, OP_IPUT_WIDE_QUICK); 1606 break; 1607 case OP_IPUT_OBJECT: 1608 rewriteInstField(method, insns, OP_IPUT_OBJECT_QUICK); 1609 break; 1610 1611 case OP_INVOKE_VIRTUAL: 1612 if (!rewriteExecuteInline(method, insns, METHOD_VIRTUAL,inlineSubs)) 1613 { 1614 if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_VIRTUAL_QUICK)) 1615 return false; 1616 } 1617 break; 1618 case OP_INVOKE_VIRTUAL_RANGE: 1619 if (!rewriteExecuteInlineRange(method, insns, METHOD_VIRTUAL, 1620 inlineSubs)) 1621 { 1622 if (!rewriteVirtualInvoke(method, insns, 1623 OP_INVOKE_VIRTUAL_QUICK_RANGE)) 1624 { 1625 return false; 1626 } 1627 } 1628 break; 1629 case OP_INVOKE_SUPER: 1630 if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK)) 1631 return false; 1632 break; 1633 case OP_INVOKE_SUPER_RANGE: 1634 if (!rewriteVirtualInvoke(method, insns, OP_INVOKE_SUPER_QUICK_RANGE)) 1635 return false; 1636 break; 1637 1638 case OP_INVOKE_DIRECT: 1639 if (!rewriteExecuteInline(method, insns, METHOD_DIRECT, inlineSubs)) 1640 { 1641 if (!rewriteEmptyDirectInvoke(method, insns)) 1642 return false; 1643 } 1644 break; 1645 case OP_INVOKE_DIRECT_RANGE: 1646 rewriteExecuteInlineRange(method, insns, METHOD_DIRECT, inlineSubs); 1647 break; 1648 1649 case OP_INVOKE_STATIC: 1650 rewriteExecuteInline(method, insns, METHOD_STATIC, inlineSubs); 1651 break; 1652 case OP_INVOKE_STATIC_RANGE: 1653 rewriteExecuteInlineRange(method, insns, METHOD_STATIC, inlineSubs); 1654 break; 1655 1656 default: 1657 // ignore this instruction 1658 ; 1659 } 1660 1661 if (*insns == kPackedSwitchSignature) { 1662 width = 4 + insns[1] * 2; 1663 } else if (*insns == kSparseSwitchSignature) { 1664 width = 2 + insns[1] * 4; 1665 } else if (*insns == kArrayDataSignature) { 1666 u2 elemWidth = insns[1]; 1667 u4 len = insns[2] | (((u4)insns[3]) << 16); 1668 width = 4 + (elemWidth * len + 1) / 2; 1669 } else { 1670 width = dexGetInstrWidth(gDvm.instrWidth, inst); 1671 } 1672 assert(width > 0); 1673 1674 insns += width; 1675 insnsSize -= width; 1676 } 1677 1678 assert(insnsSize == 0); 1679 return true; 1680} 1681 1682 1683/* 1684 * If "referrer" and "resClass" don't come from the same DEX file, and 1685 * the DEX we're working on is not destined for the bootstrap class path, 1686 * tweak the class loader so package-access checks work correctly. 1687 * 1688 * Only do this if we're doing pre-verification or optimization. 1689 */ 1690static void tweakLoader(ClassObject* referrer, ClassObject* resClass) 1691{ 1692 if (!gDvm.optimizing) 1693 return; 1694 assert(referrer->classLoader == NULL); 1695 assert(resClass->classLoader == NULL); 1696 1697 if (!gDvm.optimizingBootstrapClass) { 1698 /* class loader for an array class comes from element type */ 1699 if (dvmIsArrayClass(resClass)) 1700 resClass = resClass->elementClass; 1701 if (referrer->pDvmDex != resClass->pDvmDex) 1702 resClass->classLoader = (Object*) 0xdead3333; 1703 } 1704} 1705 1706/* 1707 * Undo the effects of tweakLoader. 1708 */ 1709static void untweakLoader(ClassObject* referrer, ClassObject* resClass) 1710{ 1711 if (!gDvm.optimizing || gDvm.optimizingBootstrapClass) 1712 return; 1713 1714 if (dvmIsArrayClass(resClass)) 1715 resClass = resClass->elementClass; 1716 resClass->classLoader = NULL; 1717} 1718 1719 1720/* 1721 * Alternate version of dvmResolveClass for use with verification and 1722 * optimization. Performs access checks on every resolve, and refuses 1723 * to acknowledge the existence of classes defined in more than one DEX 1724 * file. 1725 * 1726 * Exceptions caused by failures are cleared before returning. 1727 * 1728 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL. 1729 */ 1730ClassObject* dvmOptResolveClass(ClassObject* referrer, u4 classIdx, 1731 VerifyError* pFailure) 1732{ 1733 DvmDex* pDvmDex = referrer->pDvmDex; 1734 ClassObject* resClass; 1735 1736 /* 1737 * Check the table first. If not there, do the lookup by name. 1738 */ 1739 resClass = dvmDexGetResolvedClass(pDvmDex, classIdx); 1740 if (resClass == NULL) { 1741 const char* className = dexStringByTypeIdx(pDvmDex->pDexFile, classIdx); 1742 if (className[0] != '\0' && className[1] == '\0') { 1743 /* primitive type */ 1744 resClass = dvmFindPrimitiveClass(className[0]); 1745 } else { 1746 resClass = dvmFindClassNoInit(className, referrer->classLoader); 1747 } 1748 if (resClass == NULL) { 1749 /* not found, exception should be raised */ 1750 LOGV("DexOpt: class %d (%s) not found\n", 1751 classIdx, 1752 dexStringByTypeIdx(pDvmDex->pDexFile, classIdx)); 1753 if (pFailure != NULL) { 1754 /* dig through the wrappers to find the original failure */ 1755 Object* excep = dvmGetException(dvmThreadSelf()); 1756 while (true) { 1757 Object* cause = dvmGetExceptionCause(excep); 1758 if (cause == NULL) 1759 break; 1760 excep = cause; 1761 } 1762 if (strcmp(excep->clazz->descriptor, 1763 "Ljava/lang/IncompatibleClassChangeError;") == 0) 1764 { 1765 *pFailure = VERIFY_ERROR_CLASS_CHANGE; 1766 } else { 1767 *pFailure = VERIFY_ERROR_NO_CLASS; 1768 } 1769 } 1770 dvmClearOptException(dvmThreadSelf()); 1771 return NULL; 1772 } 1773 1774 /* 1775 * Add it to the resolved table so we're faster on the next lookup. 1776 */ 1777 dvmDexSetResolvedClass(pDvmDex, classIdx, resClass); 1778 } 1779 1780 /* multiple definitions? */ 1781 if (IS_CLASS_FLAG_SET(resClass, CLASS_MULTIPLE_DEFS)) { 1782 LOGI("DexOpt: not resolving ambiguous class '%s'\n", 1783 resClass->descriptor); 1784 if (pFailure != NULL) 1785 *pFailure = VERIFY_ERROR_NO_CLASS; 1786 return NULL; 1787 } 1788 1789 /* access allowed? */ 1790 tweakLoader(referrer, resClass); 1791 bool allowed = dvmCheckClassAccess(referrer, resClass); 1792 untweakLoader(referrer, resClass); 1793 if (!allowed) { 1794 LOGW("DexOpt: resolve class illegal access: %s -> %s\n", 1795 referrer->descriptor, resClass->descriptor); 1796 if (pFailure != NULL) 1797 *pFailure = VERIFY_ERROR_ACCESS_CLASS; 1798 return NULL; 1799 } 1800 1801 return resClass; 1802} 1803 1804/* 1805 * Alternate version of dvmResolveInstField(). 1806 * 1807 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL. 1808 */ 1809InstField* dvmOptResolveInstField(ClassObject* referrer, u4 ifieldIdx, 1810 VerifyError* pFailure) 1811{ 1812 DvmDex* pDvmDex = referrer->pDvmDex; 1813 InstField* resField; 1814 1815 resField = (InstField*) dvmDexGetResolvedField(pDvmDex, ifieldIdx); 1816 if (resField == NULL) { 1817 const DexFieldId* pFieldId; 1818 ClassObject* resClass; 1819 1820 pFieldId = dexGetFieldId(pDvmDex->pDexFile, ifieldIdx); 1821 1822 /* 1823 * Find the field's class. 1824 */ 1825 resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure); 1826 if (resClass == NULL) { 1827 //dvmClearOptException(dvmThreadSelf()); 1828 assert(!dvmCheckException(dvmThreadSelf())); 1829 if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); } 1830 return NULL; 1831 } 1832 1833 resField = (InstField*)dvmFindFieldHier(resClass, 1834 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx), 1835 dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx)); 1836 if (resField == NULL) { 1837 LOGD("DexOpt: couldn't find field %s.%s\n", 1838 resClass->descriptor, 1839 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); 1840 if (pFailure != NULL) 1841 *pFailure = VERIFY_ERROR_NO_FIELD; 1842 return NULL; 1843 } 1844 if (dvmIsStaticField(&resField->field)) { 1845 LOGD("DexOpt: wanted instance, got static for field %s.%s\n", 1846 resClass->descriptor, 1847 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); 1848 if (pFailure != NULL) 1849 *pFailure = VERIFY_ERROR_CLASS_CHANGE; 1850 return NULL; 1851 } 1852 1853 /* 1854 * Add it to the resolved table so we're faster on the next lookup. 1855 */ 1856 dvmDexSetResolvedField(pDvmDex, ifieldIdx, (Field*) resField); 1857 } 1858 1859 /* access allowed? */ 1860 tweakLoader(referrer, resField->field.clazz); 1861 bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField); 1862 untweakLoader(referrer, resField->field.clazz); 1863 if (!allowed) { 1864 LOGI("DexOpt: access denied from %s to field %s.%s\n", 1865 referrer->descriptor, resField->field.clazz->descriptor, 1866 resField->field.name); 1867 if (pFailure != NULL) 1868 *pFailure = VERIFY_ERROR_ACCESS_FIELD; 1869 return NULL; 1870 } 1871 1872 return resField; 1873} 1874 1875/* 1876 * Alternate version of dvmResolveStaticField(). 1877 * 1878 * Does not force initialization of the resolved field's class. 1879 * 1880 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL. 1881 */ 1882StaticField* dvmOptResolveStaticField(ClassObject* referrer, u4 sfieldIdx, 1883 VerifyError* pFailure) 1884{ 1885 DvmDex* pDvmDex = referrer->pDvmDex; 1886 StaticField* resField; 1887 1888 resField = (StaticField*)dvmDexGetResolvedField(pDvmDex, sfieldIdx); 1889 if (resField == NULL) { 1890 const DexFieldId* pFieldId; 1891 ClassObject* resClass; 1892 1893 pFieldId = dexGetFieldId(pDvmDex->pDexFile, sfieldIdx); 1894 1895 /* 1896 * Find the field's class. 1897 */ 1898 resClass = dvmOptResolveClass(referrer, pFieldId->classIdx, pFailure); 1899 if (resClass == NULL) { 1900 //dvmClearOptException(dvmThreadSelf()); 1901 assert(!dvmCheckException(dvmThreadSelf())); 1902 if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); } 1903 return NULL; 1904 } 1905 1906 resField = (StaticField*)dvmFindFieldHier(resClass, 1907 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx), 1908 dexStringByTypeIdx(pDvmDex->pDexFile, pFieldId->typeIdx)); 1909 if (resField == NULL) { 1910 LOGD("DexOpt: couldn't find static field\n"); 1911 if (pFailure != NULL) 1912 *pFailure = VERIFY_ERROR_NO_FIELD; 1913 return NULL; 1914 } 1915 if (!dvmIsStaticField(&resField->field)) { 1916 LOGD("DexOpt: wanted static, got instance for field %s.%s\n", 1917 resClass->descriptor, 1918 dexStringById(pDvmDex->pDexFile, pFieldId->nameIdx)); 1919 if (pFailure != NULL) 1920 *pFailure = VERIFY_ERROR_CLASS_CHANGE; 1921 return NULL; 1922 } 1923 1924 /* 1925 * Add it to the resolved table so we're faster on the next lookup. 1926 * 1927 * We can only do this if we're in "dexopt", because the presence 1928 * of a valid value in the resolution table implies that the class 1929 * containing the static field has been initialized. 1930 */ 1931 if (gDvm.optimizing) 1932 dvmDexSetResolvedField(pDvmDex, sfieldIdx, (Field*) resField); 1933 } 1934 1935 /* access allowed? */ 1936 tweakLoader(referrer, resField->field.clazz); 1937 bool allowed = dvmCheckFieldAccess(referrer, (Field*)resField); 1938 untweakLoader(referrer, resField->field.clazz); 1939 if (!allowed) { 1940 LOGI("DexOpt: access denied from %s to field %s.%s\n", 1941 referrer->descriptor, resField->field.clazz->descriptor, 1942 resField->field.name); 1943 if (pFailure != NULL) 1944 *pFailure = VERIFY_ERROR_ACCESS_FIELD; 1945 return NULL; 1946 } 1947 1948 return resField; 1949} 1950 1951 1952/* 1953 * Rewrite an iget/iput instruction. These all have the form: 1954 * op vA, vB, field@CCCC 1955 * 1956 * Where vA holds the value, vB holds the object reference, and CCCC is 1957 * the field reference constant pool offset. We want to replace CCCC 1958 * with the byte offset from the start of the object. 1959 * 1960 * "clazz" is the referring class. We need this because we verify 1961 * access rights here. 1962 */ 1963static void rewriteInstField(Method* method, u2* insns, OpCode newOpc) 1964{ 1965 ClassObject* clazz = method->clazz; 1966 u2 fieldIdx = insns[1]; 1967 InstField* field; 1968 int byteOffset; 1969 1970 field = dvmOptResolveInstField(clazz, fieldIdx, NULL); 1971 if (field == NULL) { 1972 LOGI("DexOpt: unable to optimize field ref 0x%04x at 0x%02x in %s.%s\n", 1973 fieldIdx, (int) (insns - method->insns), clazz->descriptor, 1974 method->name); 1975 return; 1976 } 1977 1978 if (field->byteOffset >= 65536) { 1979 LOGI("DexOpt: field offset exceeds 64K (%d)\n", field->byteOffset); 1980 return; 1981 } 1982 1983 insns[0] = (insns[0] & 0xff00) | (u2) newOpc; 1984 insns[1] = (u2) field->byteOffset; 1985 LOGVV("DexOpt: rewrote access to %s.%s --> %d\n", 1986 field->field.clazz->descriptor, field->field.name, 1987 field->byteOffset); 1988} 1989 1990/* 1991 * Alternate version of dvmResolveMethod(). 1992 * 1993 * Doesn't throw exceptions, and checks access on every lookup. 1994 * 1995 * On failure, returns NULL, and sets *pFailure if pFailure is not NULL. 1996 */ 1997Method* dvmOptResolveMethod(ClassObject* referrer, u4 methodIdx, 1998 MethodType methodType, VerifyError* pFailure) 1999{ 2000 DvmDex* pDvmDex = referrer->pDvmDex; 2001 Method* resMethod; 2002 2003 assert(methodType == METHOD_DIRECT || 2004 methodType == METHOD_VIRTUAL || 2005 methodType == METHOD_STATIC); 2006 2007 LOGVV("--- resolving method %u (referrer=%s)\n", methodIdx, 2008 referrer->descriptor); 2009 2010 resMethod = dvmDexGetResolvedMethod(pDvmDex, methodIdx); 2011 if (resMethod == NULL) { 2012 const DexMethodId* pMethodId; 2013 ClassObject* resClass; 2014 2015 pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx); 2016 2017 resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, pFailure); 2018 if (resClass == NULL) { 2019 /* 2020 * Can't find the class that the method is a part of, or don't 2021 * have permission to access the class. 2022 */ 2023 LOGV("DexOpt: can't find called method's class (?.%s)\n", 2024 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx)); 2025 if (pFailure != NULL) { assert(!VERIFY_OK(*pFailure)); } 2026 return NULL; 2027 } 2028 if (dvmIsInterfaceClass(resClass)) { 2029 /* method is part of an interface; this is wrong method for that */ 2030 LOGW("DexOpt: method is in an interface\n"); 2031 if (pFailure != NULL) 2032 *pFailure = VERIFY_ERROR_GENERIC; 2033 return NULL; 2034 } 2035 2036 /* 2037 * We need to chase up the class hierarchy to find methods defined 2038 * in super-classes. (We only want to check the current class 2039 * if we're looking for a constructor.) 2040 */ 2041 DexProto proto; 2042 dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId); 2043 2044 if (methodType == METHOD_DIRECT) { 2045 resMethod = dvmFindDirectMethod(resClass, 2046 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto); 2047 } else { 2048 /* METHOD_STATIC or METHOD_VIRTUAL */ 2049 resMethod = dvmFindMethodHier(resClass, 2050 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), &proto); 2051 } 2052 2053 if (resMethod == NULL) { 2054 LOGV("DexOpt: couldn't find method '%s'\n", 2055 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx)); 2056 if (pFailure != NULL) 2057 *pFailure = VERIFY_ERROR_NO_METHOD; 2058 return NULL; 2059 } 2060 if (methodType == METHOD_STATIC) { 2061 if (!dvmIsStaticMethod(resMethod)) { 2062 LOGD("DexOpt: wanted static, got instance for method %s.%s\n", 2063 resClass->descriptor, resMethod->name); 2064 if (pFailure != NULL) 2065 *pFailure = VERIFY_ERROR_CLASS_CHANGE; 2066 return NULL; 2067 } 2068 } else if (methodType == METHOD_VIRTUAL) { 2069 if (dvmIsStaticMethod(resMethod)) { 2070 LOGD("DexOpt: wanted instance, got static for method %s.%s\n", 2071 resClass->descriptor, resMethod->name); 2072 if (pFailure != NULL) 2073 *pFailure = VERIFY_ERROR_CLASS_CHANGE; 2074 return NULL; 2075 } 2076 } 2077 2078 /* see if this is a pure-abstract method */ 2079 if (dvmIsAbstractMethod(resMethod) && !dvmIsAbstractClass(resClass)) { 2080 LOGW("DexOpt: pure-abstract method '%s' in %s\n", 2081 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx), 2082 resClass->descriptor); 2083 if (pFailure != NULL) 2084 *pFailure = VERIFY_ERROR_GENERIC; 2085 return NULL; 2086 } 2087 2088 /* 2089 * Add it to the resolved table so we're faster on the next lookup. 2090 * 2091 * We can only do this for static methods if we're not in "dexopt", 2092 * because the presence of a valid value in the resolution table 2093 * implies that the class containing the static field has been 2094 * initialized. 2095 */ 2096 if (methodType != METHOD_STATIC || gDvm.optimizing) 2097 dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod); 2098 } 2099 2100 LOGVV("--- found method %d (%s.%s)\n", 2101 methodIdx, resMethod->clazz->descriptor, resMethod->name); 2102 2103 /* access allowed? */ 2104 tweakLoader(referrer, resMethod->clazz); 2105 bool allowed = dvmCheckMethodAccess(referrer, resMethod); 2106 untweakLoader(referrer, resMethod->clazz); 2107 if (!allowed) { 2108 IF_LOGI() { 2109 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype); 2110 LOGI("DexOpt: illegal method access (call %s.%s %s from %s)\n", 2111 resMethod->clazz->descriptor, resMethod->name, desc, 2112 referrer->descriptor); 2113 free(desc); 2114 } 2115 if (pFailure != NULL) 2116 *pFailure = VERIFY_ERROR_ACCESS_METHOD; 2117 return NULL; 2118 } 2119 2120 return resMethod; 2121} 2122 2123/* 2124 * Rewrite invoke-virtual, invoke-virtual/range, invoke-super, and 2125 * invoke-super/range. These all have the form: 2126 * op vAA, meth@BBBB, reg stuff @CCCC 2127 * 2128 * We want to replace the method constant pool index BBBB with the 2129 * vtable index. 2130 */ 2131static bool rewriteVirtualInvoke(Method* method, u2* insns, OpCode newOpc) 2132{ 2133 ClassObject* clazz = method->clazz; 2134 Method* baseMethod; 2135 u2 methodIdx = insns[1]; 2136 2137 baseMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_VIRTUAL, NULL); 2138 if (baseMethod == NULL) { 2139 LOGD("DexOpt: unable to optimize virt call 0x%04x at 0x%02x in %s.%s\n", 2140 methodIdx, 2141 (int) (insns - method->insns), clazz->descriptor, 2142 method->name); 2143 return false; 2144 } 2145 2146 assert((insns[0] & 0xff) == OP_INVOKE_VIRTUAL || 2147 (insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE || 2148 (insns[0] & 0xff) == OP_INVOKE_SUPER || 2149 (insns[0] & 0xff) == OP_INVOKE_SUPER_RANGE); 2150 2151 /* 2152 * Note: Method->methodIndex is a u2 and is range checked during the 2153 * initial load. 2154 */ 2155 insns[0] = (insns[0] & 0xff00) | (u2) newOpc; 2156 insns[1] = baseMethod->methodIndex; 2157 2158 //LOGI("DexOpt: rewrote call to %s.%s --> %s.%s\n", 2159 // method->clazz->descriptor, method->name, 2160 // baseMethod->clazz->descriptor, baseMethod->name); 2161 2162 return true; 2163} 2164 2165/* 2166 * Rewrite invoke-direct, which has the form: 2167 * op vAA, meth@BBBB, reg stuff @CCCC 2168 * 2169 * There isn't a lot we can do to make this faster, but in some situations 2170 * we can make it go away entirely. 2171 * 2172 * This must only be used when the invoked method does nothing and has 2173 * no return value (the latter being very important for verification). 2174 */ 2175static bool rewriteEmptyDirectInvoke(Method* method, u2* insns) 2176{ 2177 ClassObject* clazz = method->clazz; 2178 Method* calledMethod; 2179 u2 methodIdx = insns[1]; 2180 2181 calledMethod = dvmOptResolveMethod(clazz, methodIdx, METHOD_DIRECT, NULL); 2182 if (calledMethod == NULL) { 2183 LOGD("DexOpt: unable to opt direct call 0x%04x at 0x%02x in %s.%s\n", 2184 methodIdx, 2185 (int) (insns - method->insns), clazz->descriptor, 2186 method->name); 2187 return false; 2188 } 2189 2190 /* TODO: verify that java.lang.Object() is actually empty! */ 2191 if (calledMethod->clazz == gDvm.classJavaLangObject && 2192 dvmCompareNameDescriptorAndMethod("<init>", "()V", calledMethod) == 0) 2193 { 2194 /* 2195 * Replace with "empty" instruction. DO NOT disturb anything 2196 * else about it, as we want it to function the same as 2197 * OP_INVOKE_DIRECT when debugging is enabled. 2198 */ 2199 assert((insns[0] & 0xff) == OP_INVOKE_DIRECT); 2200 insns[0] = (insns[0] & 0xff00) | (u2) OP_INVOKE_DIRECT_EMPTY; 2201 2202 //LOGI("DexOpt: marked-empty call to %s.%s --> %s.%s\n", 2203 // method->clazz->descriptor, method->name, 2204 // calledMethod->clazz->descriptor, calledMethod->name); 2205 } 2206 2207 return true; 2208} 2209 2210/* 2211 * Resolve an interface method reference. 2212 * 2213 * No method access check here -- interface methods are always public. 2214 * 2215 * Returns NULL if the method was not found. Does not throw an exception. 2216 */ 2217Method* dvmOptResolveInterfaceMethod(ClassObject* referrer, u4 methodIdx) 2218{ 2219 DvmDex* pDvmDex = referrer->pDvmDex; 2220 Method* resMethod; 2221 int i; 2222 2223 LOGVV("--- resolving interface method %d (referrer=%s)\n", 2224 methodIdx, referrer->descriptor); 2225 2226 resMethod = dvmDexGetResolvedMethod(pDvmDex, methodIdx); 2227 if (resMethod == NULL) { 2228 const DexMethodId* pMethodId; 2229 ClassObject* resClass; 2230 2231 pMethodId = dexGetMethodId(pDvmDex->pDexFile, methodIdx); 2232 2233 resClass = dvmOptResolveClass(referrer, pMethodId->classIdx, NULL); 2234 if (resClass == NULL) { 2235 /* can't find the class that the method is a part of */ 2236 dvmClearOptException(dvmThreadSelf()); 2237 return NULL; 2238 } 2239 if (!dvmIsInterfaceClass(resClass)) { 2240 /* whoops */ 2241 LOGI("Interface method not part of interface class\n"); 2242 return NULL; 2243 } 2244 2245 const char* methodName = 2246 dexStringById(pDvmDex->pDexFile, pMethodId->nameIdx); 2247 DexProto proto; 2248 dexProtoSetFromMethodId(&proto, pDvmDex->pDexFile, pMethodId); 2249 2250 LOGVV("+++ looking for '%s' '%s' in resClass='%s'\n", 2251 methodName, methodSig, resClass->descriptor); 2252 resMethod = dvmFindVirtualMethod(resClass, methodName, &proto); 2253 if (resMethod == NULL) { 2254 /* scan superinterfaces and superclass interfaces */ 2255 LOGVV("+++ did not resolve immediately\n"); 2256 for (i = 0; i < resClass->iftableCount; i++) { 2257 resMethod = dvmFindVirtualMethod(resClass->iftable[i].clazz, 2258 methodName, &proto); 2259 if (resMethod != NULL) 2260 break; 2261 } 2262 2263 if (resMethod == NULL) { 2264 LOGVV("+++ unable to resolve method %s\n", methodName); 2265 return NULL; 2266 } 2267 } else { 2268 LOGVV("+++ resolved immediately: %s (%s %d)\n", resMethod->name, 2269 resMethod->clazz->descriptor, (u4) resMethod->methodIndex); 2270 } 2271 2272 /* we're expecting this to be abstract */ 2273 if (!dvmIsAbstractMethod(resMethod)) { 2274 char* desc = dexProtoCopyMethodDescriptor(&resMethod->prototype); 2275 LOGW("Found non-abstract interface method %s.%s %s\n", 2276 resMethod->clazz->descriptor, resMethod->name, desc); 2277 free(desc); 2278 return NULL; 2279 } 2280 2281 /* 2282 * Add it to the resolved table so we're faster on the next lookup. 2283 */ 2284 dvmDexSetResolvedMethod(pDvmDex, methodIdx, resMethod); 2285 } 2286 2287 LOGVV("--- found interface method %d (%s.%s)\n", 2288 methodIdx, resMethod->clazz->descriptor, resMethod->name); 2289 2290 /* interface methods are always public; no need to check access */ 2291 2292 return resMethod; 2293} 2294 2295/* 2296 * See if the method being called can be rewritten as an inline operation. 2297 * Works for invoke-virtual, invoke-direct, and invoke-static. 2298 * 2299 * Returns "true" if we replace it. 2300 */ 2301static bool rewriteExecuteInline(Method* method, u2* insns, 2302 MethodType methodType, const InlineSub* inlineSubs) 2303{ 2304 ClassObject* clazz = method->clazz; 2305 Method* calledMethod; 2306 u2 methodIdx = insns[1]; 2307 2308 //return false; 2309 2310 calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL); 2311 if (calledMethod == NULL) { 2312 LOGV("+++ DexOpt inline: can't find %d\n", methodIdx); 2313 return false; 2314 } 2315 2316 while (inlineSubs->method != NULL) { 2317 /* 2318 if (extra) { 2319 LOGI("comparing %p vs %p %s.%s %s\n", 2320 inlineSubs->method, calledMethod, 2321 inlineSubs->method->clazz->descriptor, 2322 inlineSubs->method->name, 2323 inlineSubs->method->signature); 2324 } 2325 */ 2326 if (inlineSubs->method == calledMethod) { 2327 assert((insns[0] & 0xff) == OP_INVOKE_DIRECT || 2328 (insns[0] & 0xff) == OP_INVOKE_STATIC || 2329 (insns[0] & 0xff) == OP_INVOKE_VIRTUAL); 2330 insns[0] = (insns[0] & 0xff00) | (u2) OP_EXECUTE_INLINE; 2331 insns[1] = (u2) inlineSubs->inlineIdx; 2332 2333 //LOGI("DexOpt: execute-inline %s.%s --> %s.%s\n", 2334 // method->clazz->descriptor, method->name, 2335 // calledMethod->clazz->descriptor, calledMethod->name); 2336 return true; 2337 } 2338 2339 inlineSubs++; 2340 } 2341 2342 return false; 2343} 2344 2345/* 2346 * See if the method being called can be rewritten as an inline operation. 2347 * Works for invoke-virtual/range, invoke-direct/range, and invoke-static/range. 2348 * 2349 * Returns "true" if we replace it. 2350 */ 2351static bool rewriteExecuteInlineRange(Method* method, u2* insns, 2352 MethodType methodType, const InlineSub* inlineSubs) 2353{ 2354 ClassObject* clazz = method->clazz; 2355 Method* calledMethod; 2356 u2 methodIdx = insns[1]; 2357 2358 calledMethod = dvmOptResolveMethod(clazz, methodIdx, methodType, NULL); 2359 if (calledMethod == NULL) { 2360 LOGV("+++ DexOpt inline/range: can't find %d\n", methodIdx); 2361 return false; 2362 } 2363 2364 while (inlineSubs->method != NULL) { 2365 if (inlineSubs->method == calledMethod) { 2366 assert((insns[0] & 0xff) == OP_INVOKE_DIRECT_RANGE || 2367 (insns[0] & 0xff) == OP_INVOKE_STATIC_RANGE || 2368 (insns[0] & 0xff) == OP_INVOKE_VIRTUAL_RANGE); 2369 insns[0] = (insns[0] & 0xff00) | (u2) OP_EXECUTE_INLINE_RANGE; 2370 insns[1] = (u2) inlineSubs->inlineIdx; 2371 2372 //LOGI("DexOpt: execute-inline/range %s.%s --> %s.%s\n", 2373 // method->clazz->descriptor, method->name, 2374 // calledMethod->clazz->descriptor, calledMethod->name); 2375 return true; 2376 } 2377 2378 inlineSubs++; 2379 } 2380 2381 return false; 2382} 2383 2384