DexPrepare.cpp revision 8521311b4e55847c650a87933d5a3f04618e4e69
12e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 22e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Copyright (C) 2008 The Android Open Source Project 32e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 42e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Licensed under the Apache License, Version 2.0 (the "License"); 52e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * you may not use this file except in compliance with the License. 62e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * You may obtain a copy of the License at 72e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 82e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * http://www.apache.org/licenses/LICENSE-2.0 92e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Unless required by applicable law or agreed to in writing, software 112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * distributed under the License is distributed on an "AS IS" BASIS, 122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * See the License for the specific language governing permissions and 142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * limitations under the License. 152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Prepare a DEX file for use by the VM. Depending upon the VM options 192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * we will attempt to verify and/or optimize the code, possibly appending 202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * register maps. 212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * TODO: the format of the optimized header is currently "whatever we 232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * happen to write", since the VM that writes it is by definition the same 242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * as the VM that reads it. Still, it should be better documented and 252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * more rigorously structured. 262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include "Dalvik.h" 282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include "libdex/OptInvocation.h" 292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include "analysis/RegisterMap.h" 302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include "analysis/Optimize.h" 312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <zlib.h> 332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <stdlib.h> 352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <unistd.h> 362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <sys/mman.h> 372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <sys/stat.h> 382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <sys/file.h> 392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <sys/wait.h> 402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <fcntl.h> 412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <errno.h> 422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* fwd */ 45cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic bool rewriteDex(u1* addr, int len, u4* pHeaderFlags, 46cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden DexClassLookup** ppClassLookup); 47cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic bool loadAllClasses(DvmDex* pDvmDex); 48cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify, 49cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden bool doOpt); 50cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz, 51cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const DexClassDef* pClassDef, bool doVerify, bool doOpt); 522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic void updateChecksum(u1* addr, int len, DexHeader* pHeader); 532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic int writeDependencies(int fd, u4 modWhen, u4 crc); 54e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinstatic bool writeOptData(int fd, const DexClassLookup* pClassLookup,\ 55d394371bd84bacc51e96e2d2eacb8549d9110b1eDan Bornstein const RegisterMapBuilder* pRegMapBuilder); 562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum); 572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Return the fd of an open file in the DEX file cache area. If the cache 612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * file doesn't exist or is out of date, this will remove the old entry, 622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * create a new one (writing only the file header), and return with the 632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * "new file" flag set. 642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * It's possible to execute from an unoptimized DEX file directly, 662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * assuming the byte ordering and structure alignment is correct, but 672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * disadvantageous because some significant optimizations are not possible. 682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * It's not generally possible to do the same from an uncompressed Jar 692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * file entry, because we have to guarantee 32-bit alignment in the 702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * memory-mapped file. 712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * For a Jar/APK file (a zip archive with "classes.dex" inside), "modWhen" 732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * and "crc32" come from the Zip directory entry. For a stand-alone DEX 742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * file, it's the modification date of the file and the Adler32 from the 752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * DEX header (which immediately follows the magic). If these don't 762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * match what's stored in the opt header, we reject the file immediately. 772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * On success, the file descriptor will be positioned just past the "opt" 792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * file header, and will be locked with flock. "*pCachedName" will point 802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * to newly-allocated storage. 812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenint dvmOpenCachedDexFile(const char* fileName, const char* cacheFileName, 832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 modWhen, u4 crc, bool isBootstrap, bool* pNewFile, bool createIfMissing) 842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int fd, cc; 862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden struct stat fdStat, fileStat; 872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bool readOnly = false; 882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden *pNewFile = false; 902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenretry: 922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Try to open the cache file. If we've been asked to, 942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * create it if it doesn't exist. 952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1; 972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (fd < 0) { 982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden fd = open(cacheFileName, O_RDONLY, 0); 992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (fd < 0) { 1002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (createIfMissing) { 1012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("Can't open dex cache '%s': %s\n", 1022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cacheFileName, strerror(errno)); 1032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return fd; 1052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden readOnly = true; 1072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 1102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Grab an exclusive lock on the cache file. If somebody else is 1112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * working on it, we'll block here until they complete. Because 1122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * we're waiting on an external resource, we go into VMWAIT mode. 1132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int oldStatus; 1152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("DexOpt: locking cache file %s (fd=%d, boot=%d)\n", 1162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cacheFileName, fd, isBootstrap); 1172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 1182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = flock(fd, LOCK_EX | LOCK_NB); 1192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0) { 1202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGD("DexOpt: sleeping on flock(%s)\n", cacheFileName); 1212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = flock(fd, LOCK_EX); 1222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmChangeStatus(NULL, oldStatus); 1242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0) { 1252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("Can't lock dex cache '%s': %d\n", cacheFileName, cc); 1262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden close(fd); 1272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return -1; 1282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("DexOpt: locked cache file\n"); 1302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 1322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Check to see if the fd we opened and locked matches the file in 1332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the filesystem. If they don't, then somebody else unlinked ours 1342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * and created a new file, and we need to use that one instead. (If 1352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * we caught them between the unlink and the create, we'll get an 1362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * ENOENT from the file stat.) 1372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = fstat(fd, &fdStat); 1392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0) { 1402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("Can't stat open file '%s'\n", cacheFileName); 1412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName); 1422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto close_fail; 1432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = stat(cacheFileName, &fileStat); 1452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0 || 1462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) 1472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 1482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGD("DexOpt: our open cache file is stale; sleeping and retrying\n"); 1492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName); 1502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flock(fd, LOCK_UN); 1512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden close(fd); 1522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden usleep(250 * 1000); /* if something is hosed, don't peg machine */ 1532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto retry; 1542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 1572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * We have the correct file open and locked. If the file size is zero, 1582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * then it was just created by us, and we want to fill in some fields 1592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * in the "opt" header and set "*pNewFile". Otherwise, we want to 1602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * verify that the fields in the header match our expectations, and 1612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * reset the file if they don't. 1622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (fdStat.st_size == 0) { 1642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (readOnly) { 1652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("DexOpt: file has zero length and isn't writable\n"); 1662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto close_fail; 1672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = dexOptCreateEmptyHeader(fd); 1692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0) 1702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto close_fail; 1712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden *pNewFile = true; 1722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("DexOpt: successfully initialized new cache file\n"); 1732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 1742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bool expectVerify, expectOpt; 1752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 176d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden if (gDvm.classVerifyMode == VERIFY_MODE_NONE) { 1772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify = false; 178d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) { 1792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify = !isBootstrap; 180d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ { 1812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify = true; 182d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } 1832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 184d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) { 1852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectOpt = false; 186d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED || 187d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden gDvm.dexOptMode == OPTIMIZE_MODE_FULL) { 1882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectOpt = expectVerify; 189d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ { 1902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectOpt = true; 191d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } 1922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("checking deps, expecting vfy=%d opt=%d\n", 1942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify, expectOpt); 1952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!dvmCheckOptHeaderAndDependencies(fd, true, modWhen, crc, 1972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify, expectOpt)) 1982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 1992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (readOnly) { 2002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 2012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * We could unlink and rewrite the file if we own it or 2022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the "sticky" bit isn't set on the directory. However, 2032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * we're not able to truncate it, which spoils things. So, 2042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * give up now. 2052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 2062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (createIfMissing) { 2072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("Cached DEX '%s' (%s) is stale and not writable\n", 2082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden fileName, cacheFileName); 2092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto close_fail; 2112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 2132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 2142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * If we truncate the existing file before unlinking it, any 2152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * process that has it mapped will fail when it tries to touch 2162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the pages. 2172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This is very important. The zygote process will have the 2192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * boot DEX files (core, framework, etc.) mapped early. If 2202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * (say) core.dex gets updated, and somebody launches an app 2212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * that uses App.dex, then App.dex gets reoptimized because it's 2222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * dependent upon the boot classes. However, dexopt will be 2232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * using the *new* core.dex to do the optimizations, while the 2242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * app will actually be running against the *old* core.dex 2252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * because it starts from zygote. 2262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Even without zygote, it's still possible for a class loader 2282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * to pull in an APK that was optimized against an older set 2292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * of DEX files. We must ensure that everything fails when a 2302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * boot DEX gets updated, and for general "why aren't my 2312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * changes doing anything" purposes its best if we just make 2322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * everything crash when a DEX they're using gets updated. 2332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 234e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden LOGD("ODEX file is stale or bad; removing and retrying (%s)\n", 235e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden cacheFileName); 2362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (ftruncate(fd, 0) != 0) { 2372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("Warning: unable to truncate cache file '%s': %s\n", 2382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cacheFileName, strerror(errno)); 2392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* keep going */ 2402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (unlink(cacheFileName) != 0) { 2422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("Warning: unable to remove cache file '%s': %d %s\n", 2432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cacheFileName, errno, strerror(errno)); 2442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* keep going; permission failure should probably be fatal */ 2452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGVV("DexOpt: unlocking cache file %s\n", cacheFileName); 2472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flock(fd, LOCK_UN); 2482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden close(fd); 2492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto retry; 2502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 2512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("DexOpt: good deps in cache file\n"); 2522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 2552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(fd >= 0); 2562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return fd; 2572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 2582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenclose_fail: 2592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flock(fd, LOCK_UN); 2602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden close(fd); 2612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return -1; 2622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 2632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 2642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 2652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Unlock the file descriptor. 2662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Returns "true" on success. 2682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 2692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbool dvmUnlockCachedDexFile(int fd) 2702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 2712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGVV("DexOpt: unlocking cache file fd=%d\n", fd); 2722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return (flock(fd, LOCK_UN) == 0); 2732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 2742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 2752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 2762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 2772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Given a descriptor for a file with DEX data in it, produce an 2782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * optimized version. 2792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * The file pointed to by "fd" is expected to be a locked shared resource 2812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * (or private); we make no efforts to enforce multi-process correctness 2822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * here. 2832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * "fileName" is only used for debug output. "modWhen" and "crc" are stored 2852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * in the dependency set. 2862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * The "isBootstrap" flag determines how the optimizer and verifier handle 2882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * package-scope access checks. When optimizing, we only load the bootstrap 2892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * class DEX files and the target DEX, so the flag determines whether the 2902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * target DEX classes are given a (synthetic) non-NULL classLoader pointer. 2912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This only really matters if the target DEX contains classes that claim to 2922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * be in the same package as bootstrap classes. 2932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * The optimizer will need to load every class in the target DEX file. 2952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This is generally undesirable, so we start a subprocess to do the 2962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * work and wait for it to complete. 2972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Returns "true" on success. All data will have been written to "fd". 2992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 3002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbool dvmOptimizeDexFile(int fd, off_t dexOffset, long dexLength, 3012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const char* fileName, u4 modWhen, u4 crc, bool isBootstrap) 3022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 3032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const char* lastPart = strrchr(fileName, '/'); 3042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (lastPart != NULL) 3052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lastPart++; 3062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden else 3072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lastPart = fileName; 3082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGD("DexOpt: --- BEGIN '%s' (bootstrap=%d) ---\n", lastPart, isBootstrap); 3102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pid_t pid; 3122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 3142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This could happen if something in our bootclasspath, which we thought 3152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * was all optimized, got rejected. 3162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 3172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.optimizing) { 3182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("Rejecting recursive optimization attempt on '%s'\n", fileName); 3192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 3202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 3212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pid = fork(); 3232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (pid == 0) { 3242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const int kUseValgrind = 0; 3252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const char* kDexOptBin = "/bin/dexopt"; 3262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const char* kValgrinder = "/usr/bin/valgrind"; 3272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const int kFixedArgCount = 10; 3282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const int kValgrindArgCount = 5; 3292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const int kMaxIntLen = 12; // '-'+10dig+'\0' -OR- 0x+8dig 3302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int bcpSize = dvmGetBootPathSize(); 3312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int argc = kFixedArgCount + bcpSize 3322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden + (kValgrindArgCount * kUseValgrind); 3332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden char* argv[argc+1]; // last entry is NULL 3342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden char values[argc][kMaxIntLen]; 3352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden char* execFile; 3362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden char* androidRoot; 3372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int flags; 3382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* change process groups, so we don't clash with ProcessManager */ 3402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden setpgid(0, 0); 3412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* full path to optimizer */ 3432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden androidRoot = getenv("ANDROID_ROOT"); 3442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (androidRoot == NULL) { 3452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("ANDROID_ROOT not set, defaulting to /system\n"); 3462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden androidRoot = "/system"; 3472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 348fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro execFile = (char*)malloc(strlen(androidRoot) + strlen(kDexOptBin) + 1); 3492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden strcpy(execFile, androidRoot); 3502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden strcat(execFile, kDexOptBin); 3512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 3532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Create arg vector. 3542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 3552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int curArg = 0; 3562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (kUseValgrind) { 3582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* probably shouldn't ship the hard-coded path */ 3592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = (char*)kValgrinder; 3602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--tool=memcheck"; 3612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--leak-check=yes"; // check for leaks too 3622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--leak-resolution=med"; // increase from 2 to 4 3632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--num-callers=16"; // default is 12 3642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(curArg == kValgrindArgCount); 3652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 3662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = execFile; 3672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--dex"; 3692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[2], "%d", DALVIK_VM_BUILD); 3712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[2]; 3722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[3], "%d", fd); 3742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[3]; 3752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[4], "%d", (int) dexOffset); 3772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[4]; 3782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[5], "%d", (int) dexLength); 3802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[5]; 3812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = (char*)fileName; 3832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[7], "%d", (int) modWhen); 3852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[7]; 3862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[8], "%d", (int) crc); 3882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[8]; 3892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags = 0; 3912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.dexOptMode != OPTIMIZE_MODE_NONE) { 3922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_OPT_ENABLED; 3932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL) 3942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_OPT_ALL; 3952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 3962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.classVerifyMode != VERIFY_MODE_NONE) { 3972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_VERIFY_ENABLED; 3982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.classVerifyMode == VERIFY_MODE_ALL) 3992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_VERIFY_ALL; 4002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (isBootstrap) 4022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_IS_BOOTSTRAP; 4032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.generateRegisterMaps) 404d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden flags |= DEXOPT_GEN_REGISTER_MAPS; 4052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[9], "%d", flags); 4062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[9]; 4072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(((!kUseValgrind && curArg == kFixedArgCount) || 4092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ((kUseValgrind && curArg == kFixedArgCount+kValgrindArgCount)))); 4102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ClassPathEntry* cpe; 4122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 4132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = cpe->fileName; 4142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(curArg == argc); 4162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg] = NULL; 4182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (kUseValgrind) 4202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden execv(kValgrinder, argv); 4212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden else 4222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden execv(execFile, argv); 4232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("execv '%s'%s failed: %s\n", execFile, 4252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden kUseValgrind ? " [valgrind]" : "", strerror(errno)); 4262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden exit(1); 4272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 4282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("DexOpt: waiting for verify+opt, pid=%d\n", (int) pid); 4292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int status; 4302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pid_t gotPid; 4312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int oldStatus; 4322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 4342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Wait for the optimization process to finish. We go into VMWAIT 4352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * mode here so GC suspension won't have to wait for us. 4362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 4372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 4382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden while (true) { 4392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden gotPid = waitpid(pid, &status, 0); 4402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gotPid == -1 && errno == EINTR) { 4412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGD("waitpid interrupted, retrying\n"); 4422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 4432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden break; 4442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmChangeStatus(NULL, oldStatus); 4472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gotPid != pid) { 4482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("waitpid failed: wanted %d, got %d: %s\n", 4492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (int) pid, (int) gotPid, strerror(errno)); 4502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 4512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 4542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGD("DexOpt: --- END '%s' (success) ---\n", lastPart); 4552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return true; 4562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 4572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("DexOpt: --- END '%s' --- status=0x%04x, process failed\n", 4582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lastPart, status); 4592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 4602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 4632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 465cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Do the actual optimization. This is executed in the dexopt process. 4662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * For best use of disk/memory, we want to extract once and perform 4682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * optimizations in place. If the file has to expand or contract 4692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * to match local structure padding/alignment expectations, we want 4702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * to do the rewrite as part of the extract, rather than extracting 4712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * into a temp file and slurping it back out. (The structure alignment 4722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * is currently correct for all platforms, and this isn't expected to 4732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * change, so we should be okay with having it already extracted.) 4742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Returns "true" on success. 4762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 4772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength, 4782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const char* fileName, u4 modWhen, u4 crc, bool isBootstrap) 4792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 4802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DexClassLookup* pClassLookup = NULL; 4812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden RegisterMapBuilder* pRegMapBuilder = NULL; 4822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 headerFlags = 0; 4832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 484cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden assert(gDvm.optimizing); 4852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4862446f44302dacac8b68fc443b6fb41833653ab34Patrick Scott LOGV("Continuing optimization (%s, isb=%d)\n", fileName, isBootstrap); 4872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(dexOffset >= 0); 4892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* quick test so we don't blow up on empty file */ 4912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (dexLength < (int) sizeof(DexHeader)) { 4922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("too small to be DEX\n"); 4932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 4942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (dexOffset < (int) sizeof(DexOptHeader)) { 4962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("not enough room for opt header\n"); 4972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 4982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bool result = false; 5012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 5032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Drop this into a global so we don't have to pass it around. We could 5042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * also add a field to DexFile, but since it only pertains to DEX 5052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * creation that probably doesn't make sense. 5062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 5072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden gDvm.optimizingBootstrapClass = isBootstrap; 5082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 5102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 5112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Map the entire file (so we don't have to worry about page 5122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * alignment). The expectation is that the output file contains 5132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * our DEX data plus room for a small header. 5142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 5152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bool success; 5162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden void* mapAddr; 5172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden mapAddr = mmap(NULL, dexOffset + dexLength, PROT_READ|PROT_WRITE, 5182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden MAP_SHARED, fd, 0); 5192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (mapAddr == MAP_FAILED) { 5202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("unable to mmap DEX cache: %s\n", strerror(errno)); 5212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 5222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 5252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Rewrite the file. Byte reordering, structure realigning, 5262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * class verification, and bytecode optimization are all performed 5272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * here. 5282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 5292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * In theory the file could change size and bits could shift around. 5302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * In practice this would be annoying to deal with, so the file 5312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * layout is designed so that it can always be rewritten in place. 5322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 5332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This sets "headerFlags" and creates the class lookup table as 5342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * part of doing the processing. 5352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 536cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden success = rewriteDex(((u1*) mapAddr) + dexOffset, dexLength, 537cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden &headerFlags, &pClassLookup); 5382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (success) { 5402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DvmDex* pDvmDex = NULL; 5412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u1* dexAddr = ((u1*) mapAddr) + dexOffset; 5422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (dvmDexFileOpenPartial(dexAddr, dexLength, &pDvmDex) != 0) { 5442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("Unable to create DexFile\n"); 5452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden success = false; 5462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 5472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 548cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * If configured to do so, generate register map output 549cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * for all verified classes. The register maps were 550cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * generated during verification, and will now be serialized. 5512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 5522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.generateRegisterMaps) { 5532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pRegMapBuilder = dvmGenerateRegisterMaps(pDvmDex); 5542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (pRegMapBuilder == NULL) { 5552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("Failed generating register maps\n"); 5562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden success = false; 5572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DexHeader* pHeader = (DexHeader*)pDvmDex->pHeader; 5612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden updateChecksum(dexAddr, dexLength, pHeader); 5622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmDexFileFree(pDvmDex); 5642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* unmap the read-write version, forcing writes to disk */ 5682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (msync(mapAddr, dexOffset + dexLength, MS_SYNC) != 0) { 5692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("msync failed: %s\n", strerror(errno)); 5702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // weird, but keep going 5712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#if 1 5732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 5742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This causes clean shutdown to fail, because we have loaded classes 5752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * that point into it. For the optimizer this isn't a problem, 5762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * because it's more efficient for the process to simply exit. 5772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Exclude this code when doing clean shutdown for valgrind. 5782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 5792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (munmap(mapAddr, dexOffset + dexLength) != 0) { 5802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("munmap failed: %s\n", strerror(errno)); 5812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 5822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#endif 5842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!success) 5862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 5872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* get start offset, and adjust deps start for 64-bit alignment */ 590e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein off_t depsOffset, optOffset, endOffset, adjOffset; 591e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein int depsLength, optLength; 5922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 optChecksum; 5932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden depsOffset = lseek(fd, 0, SEEK_END); 5952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (depsOffset < 0) { 5962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("lseek to EOF failed: %s\n", strerror(errno)); 5972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 5982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden adjOffset = (depsOffset + 7) & ~(0x07); 6002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (adjOffset != depsOffset) { 6012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("Adjusting deps start from %d to %d\n", 6022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (int) depsOffset, (int) adjOffset); 6032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden depsOffset = adjOffset; 6042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lseek(fd, depsOffset, SEEK_SET); 6052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 6082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Append the dependency list. 6092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 6102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (writeDependencies(fd, modWhen, crc) != 0) { 6112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("Failed writing dependencies\n"); 6122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 6132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 615e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein /* compute deps length, then adjust opt start for 64-bit alignment */ 616e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optOffset = lseek(fd, 0, SEEK_END); 617e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein depsLength = optOffset - depsOffset; 6182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 619e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein adjOffset = (optOffset + 7) & ~(0x07); 620e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein if (adjOffset != optOffset) { 621e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein LOGV("Adjusting opt start from %d to %d\n", 622e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein (int) optOffset, (int) adjOffset); 623e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optOffset = adjOffset; 624e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein lseek(fd, optOffset, SEEK_SET); 6252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 628e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Append any optimized pre-computed data structures. 6292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 630d394371bd84bacc51e96e2d2eacb8549d9110b1eDan Bornstein if (!writeOptData(fd, pClassLookup, pRegMapBuilder)) { 631e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein LOGW("Failed writing opt data\n"); 6322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 6332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden endOffset = lseek(fd, 0, SEEK_END); 636e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optLength = endOffset - optOffset; 6372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 638e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein /* compute checksum from start of deps to end of opt area */ 6392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!computeFileChecksum(fd, depsOffset, 640e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein (optOffset+optLength) - depsOffset, &optChecksum)) 6412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 6422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 6432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 6462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Output the "opt" header with all values filled in and a correct 6472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * magic number. 6482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 6492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DexOptHeader optHdr; 6502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memset(&optHdr, 0xff, sizeof(optHdr)); 6512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memcpy(optHdr.magic, DEX_OPT_MAGIC, 4); 6522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memcpy(optHdr.magic+4, DEX_OPT_MAGIC_VERS, 4); 6532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.dexOffset = (u4) dexOffset; 6542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.dexLength = (u4) dexLength; 6552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.depsOffset = (u4) depsOffset; 6562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.depsLength = (u4) depsLength; 657e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optHdr.optOffset = (u4) optOffset; 658e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optHdr.optLength = (u4) optLength; 6592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.flags = headerFlags; 6612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.checksum = optChecksum; 6622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 663c650d2beb66896c0cf51f737d7a39476630dd142Andy McFadden fsync(fd); /* ensure previous writes go before header is written */ 664c650d2beb66896c0cf51f737d7a39476630dd142Andy McFadden 6652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lseek(fd, 0, SEEK_SET); 66664896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden if (sysWriteFully(fd, &optHdr, sizeof(optHdr), "DexOpt opt header") != 0) 6672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 6682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("Successfully wrote DEX header\n"); 6702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden result = true; 6712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden //dvmRegisterMapDumpStats(); 6732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbail: 6752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmFreeRegisterMapBuilder(pRegMapBuilder); 6762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden free(pClassLookup); 6772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return result; 6782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 6792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 682cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Perform in-place rewrites on a memory-mapped DEX file. 683cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 684cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * This happens in a short-lived child process, so we can go nutty with 685cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * loading classes and allocating memory. 686cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 687cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic bool rewriteDex(u1* addr, int len, u4* pHeaderFlags, 688cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden DexClassLookup** ppClassLookup) 689cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden{ 690cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u8 prepWhen, loadWhen, verifyOptWhen; 691cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden DvmDex* pDvmDex = NULL; 692cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden bool doVerify, doOpt; 693cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden bool result = false; 694cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 695cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden *pHeaderFlags = 0; 696cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 697cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* if the DEX is in the wrong byte order, swap it now */ 6984b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein if (dexSwapAndVerify(addr, len) != 0) 699cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 700cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden#if __BYTE_ORDER != __LITTLE_ENDIAN 701cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden *pHeaderFlags |= DEX_OPT_FLAG_BIG; 702cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden#endif 703cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 704d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden if (gDvm.classVerifyMode == VERIFY_MODE_NONE) { 705cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden doVerify = false; 706d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) { 707cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden doVerify = !gDvm.optimizingBootstrapClass; 708d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ { 709cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden doVerify = true; 710d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } 711cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 712d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) { 713cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden doOpt = false; 714d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED || 715d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden gDvm.dexOptMode == OPTIMIZE_MODE_FULL) { 716cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden doOpt = doVerify; 717d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ { 718cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden doOpt = true; 719d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } 720cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 721cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* TODO: decide if this is actually useful */ 722cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (doVerify) 723cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden *pHeaderFlags |= DEX_FLAG_VERIFIED; 724cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (doOpt) 725cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden *pHeaderFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS; 726cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 727cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 728cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Now that the DEX file can be read directly, create a DexFile struct 729cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * for it. 730cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 731cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) { 732cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGE("Unable to create DexFile\n"); 733cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 734cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 735cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 736cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 737cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Create the class lookup table. This will eventually be appended 738cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * to the end of the .odex. 739cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 740cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden *ppClassLookup = dexCreateClassLookup(pDvmDex->pDexFile); 741cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (*ppClassLookup == NULL) 742cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 743cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 744cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 745cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * If we're not going to attempt to verify or optimize the classes, 746cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * there's no value in loading them, so bail out early. 747cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 748cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (!doVerify && !doOpt) { 749cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden result = true; 750cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 751cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 752cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 753cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* this is needed for the next part */ 754cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden pDvmDex->pDexFile->pClassLookup = *ppClassLookup; 755cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 756cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden prepWhen = dvmGetRelativeTimeUsec(); 757cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 758cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 759cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Load all classes found in this DEX file. If they fail to load for 760cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * some reason, they won't get verified (which is as it should be). 761cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 762cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (!loadAllClasses(pDvmDex)) 763cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 764cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden loadWhen = dvmGetRelativeTimeUsec(); 765cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 766cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 76765a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * Create a data structure for use by the bytecode optimizer. 76865a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * We need to look up methods in a few classes, so this may cause 76965a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * a bit of class loading. We usually do this during VM init, but 77065a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * for dexopt on core.jar the order of operations gets a bit tricky, 77165a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * so we defer it to here. 77265a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden */ 77365a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden if (!dvmCreateInlineSubsTable()) 77465a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden goto bail; 77565a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden 77665a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden /* 777cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Verify and optimize all classes in the DEX file (command-line 778cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * options permitting). 779cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 780cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * This is best-effort, so there's really no way for dexopt to 781cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * fail at this point. 782cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 783cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden verifyAndOptimizeClasses(pDvmDex->pDexFile, doVerify, doOpt); 784cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden verifyOptWhen = dvmGetRelativeTimeUsec(); 785cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 786cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const char* msgStr = "???"; 787cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (doVerify && doOpt) 788cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden msgStr = "verify+opt"; 789cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden else if (doVerify) 790cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden msgStr = "verify"; 791cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden else if (doOpt) 792cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden msgStr = "opt"; 793cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGD("DexOpt: load %dms, %s %dms\n", 794cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden (int) (loadWhen - prepWhen) / 1000, 795cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden msgStr, 796cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden (int) (verifyOptWhen - loadWhen) / 1000); 797cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 798cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden result = true; 799cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 800cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenbail: 801cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* free up storage */ 802cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden dvmDexFileFree(pDvmDex); 803cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 804cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden return result; 805cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden} 806cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 807cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden/* 808cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Try to load all classes in the specified DEX. If they have some sort 809cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * of broken dependency, e.g. their superclass lives in a different DEX 810cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * that wasn't previously loaded into the bootstrap class path, loading 811cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * will fail. This is the desired behavior. 812cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 813cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * We have no notion of class loader at this point, so we load all of 814cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * the classes with the bootstrap class loader. It turns out this has 815cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * exactly the behavior we want, and has no ill side effects because we're 816cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * running in a separate process and anything we load here will be forgotten. 817cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 818cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * We set the CLASS_MULTIPLE_DEFS flag here if we see multiple definitions. 819cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * This works because we only call here as part of optimization / pre-verify, 820cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * not during verification as part of loading a class into a running VM. 821cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 822cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * This returns "false" if the world is too screwed up to do anything 823cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * useful at all. 824cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 825cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic bool loadAllClasses(DvmDex* pDvmDex) 826cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden{ 827cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u4 count = pDvmDex->pDexFile->pHeader->classDefsSize; 828cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u4 idx; 829cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden int loaded = 0; 830cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 831cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGV("DexOpt: +++ trying to load %d classes\n", count); 832cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 833cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden dvmSetBootPathExtraDex(pDvmDex); 834cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 835cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 8368521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * At this point, it is safe -- and necessary! -- to look up the 8378521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * VM's required classes and members, even when what we are in the 8388521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * process of processing is the core library that defines these 8398521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * classes itself. 8408521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein */ 8418521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein if (!dvmInitRequiredClassesAndMembers()) { 8428521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein return false; 8438521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein } 8448521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein 8458521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein /* 8468521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * We have some circularity issues with Class and Object that are 8478521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * most easily avoided by ensuring that Object is never the first 8488521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * thing we try to find-and-initialize. The call to 8498521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * dvmFindSystemClass() here takes care of that situation. (We 8508521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * only need to do this when loading classes from the DEX file 8518521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * that contains Object, and only when Object comes first in the 8528521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * list, but it costs very little to do it in all cases.) 853cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 854cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (dvmFindSystemClass("Ljava/lang/Class;") == NULL) { 855cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGE("ERROR: java.lang.Class does not exist!\n"); 856cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden return false; 857cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 858cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 859cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden for (idx = 0; idx < count; idx++) { 860cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const DexClassDef* pClassDef; 861cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const char* classDescriptor; 862cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden ClassObject* newClass; 863cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 864cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden pClassDef = dexGetClassDef(pDvmDex->pDexFile, idx); 865cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor = 866cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden dexStringByTypeIdx(pDvmDex->pDexFile, pClassDef->classIdx); 867cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 868cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGV("+++ loading '%s'", classDescriptor); 869cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden //newClass = dvmDefineClass(pDexFile, classDescriptor, 870cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden // NULL); 871cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden newClass = dvmFindSystemClassNoInit(classDescriptor); 872cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (newClass == NULL) { 873cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGV("DexOpt: failed loading '%s'\n", classDescriptor); 874cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden dvmClearOptException(dvmThreadSelf()); 875cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else if (newClass->pDvmDex != pDvmDex) { 876cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 877cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * We don't load the new one, and we tag the first one found 878cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * with the "multiple def" flag so the resolver doesn't try 879cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * to make it available. 880cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 881cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGD("DexOpt: '%s' has an earlier definition; blocking out\n", 882cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor); 883cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden SET_CLASS_FLAG(newClass, CLASS_MULTIPLE_DEFS); 884cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else { 885cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden loaded++; 886cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 887cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 888cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGV("DexOpt: +++ successfully loaded %d classes\n", loaded); 889cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 890cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden dvmSetBootPathExtraDex(NULL); 891cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden return true; 892cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden} 893cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 894cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden/* 895cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Verify and/or optimize all classes that were successfully loaded from 896cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * this DEX file. 897cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 898cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify, 899cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden bool doOpt) 900cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden{ 901cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u4 count = pDexFile->pHeader->classDefsSize; 902cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u4 idx; 903cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 904cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden for (idx = 0; idx < count; idx++) { 905cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const DexClassDef* pClassDef; 906cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const char* classDescriptor; 907cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden ClassObject* clazz; 908cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 909cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden pClassDef = dexGetClassDef(pDexFile, idx); 910cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); 911cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 912cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* all classes are loaded into the bootstrap class loader */ 913cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden clazz = dvmLookupClass(classDescriptor, NULL, false); 914cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (clazz != NULL) { 915cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden verifyAndOptimizeClass(pDexFile, clazz, pClassDef, doVerify, doOpt); 916cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 917cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else { 918cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden // TODO: log when in verbose mode 919cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGV("DexOpt: not optimizing unavailable class '%s'\n", 920cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor); 921cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 922cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 923cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 924470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden#ifdef VERIFIER_STATS 925470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden LOGI("Verifier stats:\n"); 926470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden LOGI(" methods examined : %u\n", gDvm.verifierStats.methodsExamined); 9273f64a024dec2c080b9abde74502826b29263152aAndy McFadden LOGI(" monitor-enter methods : %u\n", gDvm.verifierStats.monEnterMethods); 928470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden LOGI(" instructions examined : %u\n", gDvm.verifierStats.instrsExamined); 929470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden LOGI(" instructions re-examined: %u\n", gDvm.verifierStats.instrsReexamined); 930470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden LOGI(" copying of register sets: %u\n", gDvm.verifierStats.copyRegCount); 931470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden LOGI(" merging of register sets: %u\n", gDvm.verifierStats.mergeRegCount); 932470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden LOGI(" ...that caused changes : %u\n", gDvm.verifierStats.mergeRegChanged); 9333f64a024dec2c080b9abde74502826b29263152aAndy McFadden LOGI(" uninit searches : %u\n", gDvm.verifierStats.uninitSearches); 9343f64a024dec2c080b9abde74502826b29263152aAndy McFadden LOGI(" max memory required : %u\n", gDvm.verifierStats.biggestAlloc); 935470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden#endif 936cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden} 937cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 938cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden/* 939cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Verify and/or optimize a specific class. 940cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 941cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz, 942cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const DexClassDef* pClassDef, bool doVerify, bool doOpt) 943cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden{ 944cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const char* classDescriptor; 945cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden bool verified = false; 946cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 9473f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden if (clazz->pDvmDex->pDexFile != pDexFile) { 9483f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden /* 9493f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * The current DEX file defined a class that is also present in the 9503f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * bootstrap class path. The class loader favored the bootstrap 9513f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * version, which means that we have a pointer to a class that is 9523f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * (a) not the one we want to examine, and (b) mapped read-only, 9533f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * so we will seg fault if we try to rewrite instructions inside it. 9543f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden */ 9553f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden LOGD("DexOpt: not verifying/optimizing '%s': multiple definitions\n", 9563f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden clazz->descriptor); 9573f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden return; 9583f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden } 9593f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden 960cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); 961cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 962cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 963cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * First, try to verify it. 964cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 965cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (doVerify) { 9663f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden if (dvmVerifyClass(clazz)) { 9673f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden /* 9683f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * Set the "is preverified" flag in the DexClassDef. We 9693f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * do it here, rather than in the ClassObject structure, 9703f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * because the DexClassDef is part of the odex file. 9713f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden */ 9723f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden assert((clazz->accessFlags & JAVA_FLAGS_MASK) == 9733f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden pClassDef->accessFlags); 9743f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISPREVERIFIED; 9753f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden verified = true; 976cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else { 9773f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden // TODO: log when in verbose mode 9783f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden LOGV("DexOpt: '%s' failed verification\n", classDescriptor); 979cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 980cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 981cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 982cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (doOpt) { 983d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden bool needVerify = (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED || 984d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden gDvm.dexOptMode == OPTIMIZE_MODE_FULL); 985d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden if (!verified && needVerify) { 986cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden LOGV("DexOpt: not optimizing '%s': not verified\n", 987cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor); 988cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else { 989fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmOptimizeClass(clazz, false); 990cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 991cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* set the flag whether or not we actually changed anything */ 992cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISOPTIMIZED; 993cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 994cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 995cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden} 996cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 997cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 998cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden/* 9992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Get the cache file name from a ClassPathEntry. 10002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 10012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic const char* getCacheFileName(const ClassPathEntry* cpe) 10022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 10032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden switch (cpe->kind) { 10042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden case kCpeJar: 10052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return dvmGetJarFileCacheFileName((JarFile*) cpe->ptr); 10062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden case kCpeDex: 10072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return dvmGetRawDexFileCacheFileName((RawDexFile*) cpe->ptr); 10082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden default: 10092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("DexOpt: unexpected cpe kind %d\n", cpe->kind); 10102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmAbort(); 10112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return NULL; 10122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 10132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 10142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 10152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 10162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Get the SHA-1 signature. 10172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 10182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic const u1* getSignature(const ClassPathEntry* cpe) 10192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 10202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DvmDex* pDvmDex; 10212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 10222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden switch (cpe->kind) { 10232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden case kCpeJar: 10242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pDvmDex = dvmGetJarFileDex((JarFile*) cpe->ptr); 10252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden break; 10262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden case kCpeDex: 10272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pDvmDex = dvmGetRawDexFileDex((RawDexFile*) cpe->ptr); 10282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden break; 10292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden default: 10302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("unexpected cpe kind %d\n", cpe->kind); 10312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmAbort(); 10322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pDvmDex = NULL; // make gcc happy 10332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 10342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 10352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(pDvmDex != NULL); 10362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return pDvmDex->pDexFile->pHeader->signature; 10372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 10382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 10392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 10402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 10412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Dependency layout: 10422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b Source file modification time, in seconds since 1970 UTC 10432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b CRC-32 from Zip entry, or Adler32 from source DEX header 10442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b Dalvik VM build number 10452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b Number of dependency entries that follow 10462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Dependency entries: 10472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b Name length (including terminating null) 10482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * var Full path of cache entry (null terminated) 10492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 20b SHA-1 signature from source DEX file 10502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 10512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * If this changes, update DEX_OPT_MAGIC_VERS. 10522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 10532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic const size_t kMinDepSize = 4 * 4; 10548b31f73c2d72cfac18125f15bc69a74d3204389bJesse Wilsonstatic const size_t kMaxDepSize = 4 * 4 + 2048; // sanity check 10552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 10562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 10572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Read the "opt" header, verify it, then read the dependencies section 10582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * and verify that data as well. 10592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 10602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * If "sourceAvail" is "true", this will verify that "modWhen" and "crc" 10612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * match up with what is stored in the header. If they don't, we reject 10622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the file so that it can be recreated from the updated original. If 10632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * "sourceAvail" isn't set, e.g. for a .odex file, we ignore these arguments. 10642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 10652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * On successful return, the file will be seeked immediately past the 10662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * "opt" header. 10672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 10682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen, 10692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 crc, bool expectVerify, bool expectOpt) 10702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 10712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DexOptHeader optHdr; 10722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u1* depData = NULL; 10732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const u1* magic; 10742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden off_t posn; 10752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int result = false; 10762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ssize_t actual; 10772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 10782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 10792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Start at the start. The "opt" header, when present, will always be 10802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the first thing in the file. 10812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 10822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (lseek(fd, 0, SEEK_SET) != 0) { 10832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("DexOpt: failed to seek to start of file: %s\n", strerror(errno)); 10842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 10852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 10862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 10872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 10882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Read and do trivial verification on the opt header. The header is 10892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * always in host byte order. 10902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1091e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden actual = read(fd, &optHdr, sizeof(optHdr)); 1092e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden if (actual < 0) { 10932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("DexOpt: failed reading opt header: %s\n", strerror(errno)); 10942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 1095e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden } else if (actual != sizeof(optHdr)) { 1096e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden LOGE("DexOpt: failed reading opt header (got %d of %zd)\n", 1097e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden (int) actual, sizeof(optHdr)); 1098e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden goto bail; 10992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden magic = optHdr.magic; 1102e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden if (memcmp(magic, DEX_MAGIC, 4) == 0) { 1103e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden /* somebody probably pointed us at the wrong file */ 1104e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden LOGD("DexOpt: expected optimized DEX, found unoptimized\n"); 1105e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden goto bail; 1106e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden } else if (memcmp(magic, DEX_OPT_MAGIC, 4) != 0) { 11072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* not a DEX file, or previous attempt was interrupted */ 11082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGD("DexOpt: incorrect opt magic number (0x%02x %02x %02x %02x)\n", 11092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden magic[0], magic[1], magic[2], magic[3]); 11102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) { 11132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("DexOpt: stale opt version (0x%02x %02x %02x %02x)\n", 11142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden magic[4], magic[5], magic[6], magic[7]); 11152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (optHdr.depsLength < kMinDepSize || optHdr.depsLength > kMaxDepSize) { 11182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("DexOpt: weird deps length %d, bailing\n", optHdr.depsLength); 11192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 11232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Do the header flags match up with what we want? 11242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 11252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This is useful because it allows us to automatically regenerate 11262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * a file when settings change (e.g. verification is now mandatory), 11272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * but can cause difficulties if the bootstrap classes we depend upon 11282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * were handled differently than the current options specify. We get 11292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * upset because they're not verified or optimized, but we're not able 11302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * to regenerate them because the installer won't let us. 11312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 11322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * (This is also of limited value when !sourceAvail.) 11332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 11342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * So, for now, we essentially ignore "expectVerify" and "expectOpt" 11352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * by limiting the match mask. 11362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 11372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * The only thing we really can't handle is incorrect byte-ordering. 11382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 11392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const u4 matchMask = DEX_OPT_FLAG_BIG; 11402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 expectedFlags = 0; 11412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#if __BYTE_ORDER != __LITTLE_ENDIAN 11422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectedFlags |= DEX_OPT_FLAG_BIG; 11432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#endif 11442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (expectVerify) 11452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectedFlags |= DEX_FLAG_VERIFIED; 11462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (expectOpt) 11472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectedFlags |= DEX_OPT_FLAG_FIELDS | DEX_OPT_FLAG_INVOCATIONS; 11482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) { 11492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)\n", 11502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectedFlags, optHdr.flags, matchMask); 11512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden posn = lseek(fd, optHdr.depsOffset, SEEK_SET); 11552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (posn < 0) { 11562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("DexOpt: seek to deps failed: %s\n", strerror(errno)); 11572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 11612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Read all of the dependency stuff into memory. 11622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 11632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden depData = (u1*) malloc(optHdr.depsLength); 11642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (depData == NULL) { 11652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("DexOpt: unable to allocate %d bytes for deps\n", 11662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.depsLength); 11672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden actual = read(fd, depData, optHdr.depsLength); 1170e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden if (actual < 0) { 1171e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden LOGW("DexOpt: failed reading deps: %s\n", strerror(errno)); 1172e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden goto bail; 1173e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden } else if (actual != (ssize_t) optHdr.depsLength) { 1174e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden LOGW("DexOpt: failed reading deps: got %d of %d\n", 1175e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden (int) actual, optHdr.depsLength); 11762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 11802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Verify simple items. 11812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 11822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const u1* ptr; 11832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 val; 11842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr = depData; 11862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val = read4LE(&ptr); 11872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (sourceAvail && val != modWhen) { 11882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGI("DexOpt: source file mod time mismatch (%08x vs %08x)\n", 11892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val, modWhen); 11902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val = read4LE(&ptr); 11932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (sourceAvail && val != crc) { 11942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGI("DexOpt: source file CRC mismatch (%08x vs %08x)\n", val, crc); 11952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val = read4LE(&ptr); 11982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (val != DALVIK_VM_BUILD) { 11992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGD("DexOpt: VM build version mismatch (%d vs %d)\n", 12002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val, DALVIK_VM_BUILD); 12012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 12052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Verify dependencies on other cached DEX files. It must match 12062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * exactly with what is currently defined in the bootclasspath. 12072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 12082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ClassPathEntry* cpe; 12092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 numDeps; 12102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden numDeps = read4LE(&ptr); 12122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("+++ DexOpt: numDeps = %d\n", numDeps); 12132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 121432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein const char* cacheFileName = 121532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein dvmPathToAbsolutePortion(getCacheFileName(cpe)); 121632bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein assert(cacheFileName != NULL); /* guaranteed by Class.c */ 121732bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein 12182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const u1* signature = getSignature(cpe); 12192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden size_t len = strlen(cacheFileName) +1; 12202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 storedStrLen; 12212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (numDeps == 0) { 12232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* more entries in bootclasspath than in deps list */ 12242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGI("DexOpt: not all deps represented\n"); 12252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden storedStrLen = read4LE(&ptr); 12292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (len != storedStrLen || 12302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden strcmp(cacheFileName, (const char*) ptr) != 0) 12312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 12322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGI("DexOpt: mismatch dep name: '%s' vs. '%s'\n", 12332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cacheFileName, ptr); 12342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += storedStrLen; 12382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (memcmp(signature, ptr, kSHA1DigestLen) != 0) { 12402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGI("DexOpt: mismatch dep signature for '%s'\n", cacheFileName); 12412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += kSHA1DigestLen; 12442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("DexOpt: dep match on '%s'\n", cacheFileName); 12462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden numDeps--; 12482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (numDeps != 0) { 12512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* more entries in deps list than in classpath */ 12522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGI("DexOpt: Some deps went away\n"); 12532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // consumed all data and no more? 12572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (ptr != depData + optHdr.depsLength) { 12582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGW("DexOpt: Spurious dep data? %d vs %d\n", 12592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (int) (ptr - depData), optHdr.depsLength); 12602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(false); 12612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden result = true; 12642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbail: 12662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden free(depData); 12672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return result; 12682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 12692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 12712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Write the dependency info to "fd" at the current file position. 12722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 12732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic int writeDependencies(int fd, u4 modWhen, u4 crc) 12742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 12752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u1* buf = NULL; 12762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int result = -1; 12772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ssize_t bufLen; 12782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ClassPathEntry* cpe; 1279e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro int numDeps; 12802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 12822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Count up the number of completed entries in the bootclasspath. 12832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 12842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden numDeps = 0; 12852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bufLen = 0; 12862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 128732bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein const char* cacheFileName = 128832bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein dvmPathToAbsolutePortion(getCacheFileName(cpe)); 128932bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein assert(cacheFileName != NULL); /* guaranteed by Class.c */ 129032bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein 12912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("+++ DexOpt: found dep '%s'\n", cacheFileName); 12922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden numDeps++; 12942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bufLen += strlen(cacheFileName) +1; 12952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bufLen += 4*4 + numDeps * (4+kSHA1DigestLen); 12982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1299fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro buf = (u1*)malloc(bufLen); 13002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(buf+0, modWhen); 13022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(buf+4, crc); 13032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(buf+8, DALVIK_VM_BUILD); 13042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(buf+12, numDeps); 13052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // TODO: do we want to add dvmGetInlineOpsTableLength() here? Won't 13072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // help us if somebody replaces an existing entry, but it'd catch 13082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // additions/removals. 13092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u1* ptr = buf + 4*4; 13112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 131232bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein const char* cacheFileName = 131332bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein dvmPathToAbsolutePortion(getCacheFileName(cpe)); 131432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein assert(cacheFileName != NULL); /* guaranteed by Class.c */ 131532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein 13162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const u1* signature = getSignature(cpe); 13172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int len = strlen(cacheFileName) +1; 13182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (ptr + 4 + len + kSHA1DigestLen > buf + bufLen) { 13202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("DexOpt: overran buffer\n"); 13212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmAbort(); 13222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(ptr, len); 13252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += 4; 13262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memcpy(ptr, cacheFileName, len); 13272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += len; 13282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memcpy(ptr, signature, kSHA1DigestLen); 13292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += kSHA1DigestLen; 13302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(ptr == buf + bufLen); 13332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 133464896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden result = sysWriteFully(fd, buf, bufLen, "DexOpt dep info"); 13352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden free(buf); 13372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return result; 13382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 13392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 13422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Write a block of data in "chunk" format. 13432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 13442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * The chunk header fields are always in "native" byte order. If "size" 13452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * is not a multiple of 8 bytes, the data area is padded out. 13462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 13472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic bool writeChunk(int fd, u4 type, const void* data, size_t size) 13482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 13492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden union { /* save a syscall by grouping these together */ 13502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden char raw[8]; 13512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden struct { 13522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 type; 13532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 size; 13542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } ts; 13552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } header; 13562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(sizeof(header) == 8); 13582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("Writing chunk, type=%.4s size=%d\n", (char*) &type, size); 13602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden header.ts.type = type; 13622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden header.ts.size = (u4) size; 136364896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden if (sysWriteFully(fd, &header, sizeof(header), 1364e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein "DexOpt opt chunk header write") != 0) 136564896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden { 13662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 13672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (size > 0) { 1370e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein if (sysWriteFully(fd, data, size, "DexOpt opt chunk write") != 0) 13712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 13722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* if necessary, pad to 64-bit alignment */ 13752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if ((size & 7) != 0) { 13762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int padSize = 8 - (size & 7); 13772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGV("size was %d, inserting %d pad bytes\n", size, padSize); 13782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lseek(fd, padSize, SEEK_CUR); 13792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert( ((int)lseek(fd, 0, SEEK_CUR) & 7) == 0); 13822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return true; 13842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 13852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 1387e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Write opt data. 13882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 13892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * We have different pieces, some of which may be optional. To make the 13902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * most effective use of space, we use a "chunk" format, with a 4-byte 13912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * type and a 4-byte length. We guarantee 64-bit alignment for the data, 13922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * so it can be used directly when the file is mapped for reading. 13932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1394e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinstatic bool writeOptData(int fd, const DexClassLookup* pClassLookup, 1395d394371bd84bacc51e96e2d2eacb8549d9110b1eDan Bornstein const RegisterMapBuilder* pRegMapBuilder) 13962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 13972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* pre-computed class lookup hash table */ 13982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!writeChunk(fd, (u4) kDexChunkClassLookup, 13992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pClassLookup, pClassLookup->size)) 14002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 14012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 14022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* register maps (optional) */ 14052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (pRegMapBuilder != NULL) { 14062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!writeChunk(fd, (u4) kDexChunkRegisterMaps, 14072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pRegMapBuilder->data, pRegMapBuilder->size)) 14082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 14092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 14102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* write the end marker */ 14142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!writeChunk(fd, (u4) kDexChunkEnd, NULL, 0)) { 14152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 14162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return true; 14192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 14202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 14222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Compute a checksum on a piece of an open file. 14232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 14242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * File will be positioned at end of checksummed area. 14252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 14262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Returns "true" on success. 14272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 14282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum) 14292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 14302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden unsigned char readBuf[8192]; 14312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ssize_t actual; 14322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden uLong adler; 14332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (lseek(fd, start, SEEK_SET) != start) { 14352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("Unable to seek to start of checksum area (%ld): %s\n", 14362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (long) start, strerror(errno)); 14372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 14382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden adler = adler32(0L, Z_NULL, 0); 14412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden while (length != 0) { 14432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden size_t wanted = (length < sizeof(readBuf)) ? length : sizeof(readBuf); 14442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden actual = read(fd, readBuf, wanted); 14452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (actual <= 0) { 14462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden LOGE("Read failed (%d) while computing checksum (len=%zu): %s\n", 14472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (int) actual, length, strerror(errno)); 14482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 14492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden adler = adler32(adler, readBuf, actual); 14522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden length -= actual; 14542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden *pSum = adler; 14572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return true; 14582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 14592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 14612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Update the Adler-32 checksum stored in the DEX file. This covers the 14622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * swapped and optimized DEX data, but does not include the opt header 1463e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * or optimized data. 14642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 14652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic void updateChecksum(u1* addr, int len, DexHeader* pHeader) 14662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 14672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 14682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Rewrite the checksum. We leave the SHA-1 signature alone. 14692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 14702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden uLong adler = adler32(0L, Z_NULL, 0); 14712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum); 14722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden adler = adler32(adler, addr + nonSum, len - nonSum); 14742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pHeader->checksum = adler; 14752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 1476