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 320fbb7030fff58e25718291811394487d95d95a3eElliott Hughes#include <string> 332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 346f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein#include <libgen.h> 352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <stdlib.h> 362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <unistd.h> 372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <sys/mman.h> 382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <sys/stat.h> 392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <sys/file.h> 406f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein#include <sys/stat.h> 416f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein#include <sys/types.h> 422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <sys/wait.h> 432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <fcntl.h> 442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#include <errno.h> 456f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein#include <unistd.h> 460fbb7030fff58e25718291811394487d95d95a3eElliott Hughes#include <zlib.h> 472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* fwd */ 4957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFaddenstatic bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt, 5057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden DexClassLookup** ppClassLookup, DvmDex** ppDvmDex); 51cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic bool loadAllClasses(DvmDex* pDvmDex); 52cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify, 53cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden bool doOpt); 54cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz, 55cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const DexClassDef* pClassDef, bool doVerify, bool doOpt); 562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic void updateChecksum(u1* addr, int len, DexHeader* pHeader); 572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic int writeDependencies(int fd, u4 modWhen, u4 crc); 58e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinstatic bool writeOptData(int fd, const DexClassLookup* pClassLookup,\ 59d394371bd84bacc51e96e2d2eacb8549d9110b1eDan Bornstein const RegisterMapBuilder* pRegMapBuilder); 602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum); 612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 626f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein/* 630fbb7030fff58e25718291811394487d95d95a3eElliott Hughes * Get just the directory portion of the given path. Equivalent to dirname(3). 646f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein */ 650fbb7030fff58e25718291811394487d95d95a3eElliott Hughesstatic std::string saneDirName(const std::string& path) { 660fbb7030fff58e25718291811394487d95d95a3eElliott Hughes size_t n = path.rfind('/'); 670fbb7030fff58e25718291811394487d95d95a3eElliott Hughes if (n == std::string::npos) { 680fbb7030fff58e25718291811394487d95d95a3eElliott Hughes return "."; 696f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein } 700fbb7030fff58e25718291811394487d95d95a3eElliott Hughes return path.substr(0, n); 716f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein} 726f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein 736f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein/* 746f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein * Helper for dvmOpenCacheDexFile() in a known-error case: Check to 756f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein * see if the directory part of the given path (all but the last 766f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein * component) exists and is writable. Complain to the log if not. 776f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein */ 780fbb7030fff58e25718291811394487d95d95a3eElliott Hughesstatic bool directoryIsValid(const std::string& fileName) 796f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein{ 800fbb7030fff58e25718291811394487d95d95a3eElliott Hughes std::string dirName(saneDirName(fileName)); 816f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein 820fbb7030fff58e25718291811394487d95d95a3eElliott Hughes struct stat sb; 830fbb7030fff58e25718291811394487d95d95a3eElliott Hughes if (stat(dirName.c_str(), &sb) < 0) { 84c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Could not stat dex cache directory '%s': %s", dirName.c_str(), strerror(errno)); 856f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein return false; 866f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein } 876f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein 880fbb7030fff58e25718291811394487d95d95a3eElliott Hughes if (!S_ISDIR(sb.st_mode)) { 89c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Dex cache directory isn't a directory: %s", dirName.c_str()); 900fbb7030fff58e25718291811394487d95d95a3eElliott Hughes return false; 916f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein } 926f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein 93a78b1255ad1ce8dcacad21338d4f88db4231c4cdAndy McFadden if (access(dirName.c_str(), W_OK) < 0) { 94c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Dex cache directory isn't writable: %s", dirName.c_str()); 950fbb7030fff58e25718291811394487d95d95a3eElliott Hughes return false; 966f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein } 976f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein 98a78b1255ad1ce8dcacad21338d4f88db4231c4cdAndy McFadden if (access(dirName.c_str(), R_OK) < 0) { 99c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Dex cache directory isn't readable: %s", dirName.c_str()); 1000fbb7030fff58e25718291811394487d95d95a3eElliott Hughes return false; 1016f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein } 1026f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein 1030fbb7030fff58e25718291811394487d95d95a3eElliott Hughes return true; 1046f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein} 1052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 1072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Return the fd of an open file in the DEX file cache area. If the cache 1082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * file doesn't exist or is out of date, this will remove the old entry, 1092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * create a new one (writing only the file header), and return with the 1102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * "new file" flag set. 1112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 1122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * It's possible to execute from an unoptimized DEX file directly, 1132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * assuming the byte ordering and structure alignment is correct, but 1142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * disadvantageous because some significant optimizations are not possible. 1152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * It's not generally possible to do the same from an uncompressed Jar 1162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * file entry, because we have to guarantee 32-bit alignment in the 1172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * memory-mapped file. 1182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 1192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * For a Jar/APK file (a zip archive with "classes.dex" inside), "modWhen" 1202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * and "crc32" come from the Zip directory entry. For a stand-alone DEX 1212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * file, it's the modification date of the file and the Adler32 from the 1222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * DEX header (which immediately follows the magic). If these don't 1232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * match what's stored in the opt header, we reject the file immediately. 1242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 1252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * On success, the file descriptor will be positioned just past the "opt" 1262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * file header, and will be locked with flock. "*pCachedName" will point 1272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * to newly-allocated storage. 1282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenint dvmOpenCachedDexFile(const char* fileName, const char* cacheFileName, 1302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 modWhen, u4 crc, bool isBootstrap, bool* pNewFile, bool createIfMissing) 1312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 1322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int fd, cc; 1332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden struct stat fdStat, fileStat; 1342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bool readOnly = false; 1352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden *pNewFile = false; 1372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenretry: 1392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 1402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Try to open the cache file. If we've been asked to, 1412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * create it if it doesn't exist. 1422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden fd = createIfMissing ? open(cacheFileName, O_CREAT|O_RDWR, 0644) : -1; 1442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (fd < 0) { 1452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden fd = open(cacheFileName, O_RDONLY, 0); 1462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (fd < 0) { 1472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (createIfMissing) { 1480fbb7030fff58e25718291811394487d95d95a3eElliott Hughes // TODO: write an equivalent of strerror_r that returns a std::string. 1490fbb7030fff58e25718291811394487d95d95a3eElliott Hughes const std::string errnoString(strerror(errno)); 1506f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein if (directoryIsValid(cacheFileName)) { 151c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Can't open dex cache file '%s': %s", cacheFileName, errnoString.c_str()); 1526f9edbe7d3a83f7741c4d56f9f5be1414ecabc9fDan Bornstein } 1532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return fd; 1552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden readOnly = true; 157780d3e25adde11603bb6bab1b42a1e8e985aec15Nick Kralevich } else { 158780d3e25adde11603bb6bab1b42a1e8e985aec15Nick Kralevich fchmod(fd, 0644); 1592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 1622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Grab an exclusive lock on the cache file. If somebody else is 1632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * working on it, we'll block here until they complete. Because 1642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * we're waiting on an external resource, we go into VMWAIT mode. 1652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 16692c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: locking cache file %s (fd=%d, boot=%d)", 1672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cacheFileName, fd, isBootstrap); 1681813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro ThreadStatus oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 1692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = flock(fd, LOCK_EX | LOCK_NB); 1702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0) { 171062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("DexOpt: sleeping on flock(%s)", cacheFileName); 1722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = flock(fd, LOCK_EX); 1732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmChangeStatus(NULL, oldStatus); 1752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0) { 176c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Can't lock dex cache '%s': %d", cacheFileName, cc); 1772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden close(fd); 1782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return -1; 1792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 18092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: locked cache file"); 1812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 1832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Check to see if the fd we opened and locked matches the file in 1842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the filesystem. If they don't, then somebody else unlinked ours 1852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * and created a new file, and we need to use that one instead. (If 1862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * we caught them between the unlink and the create, we'll get an 1872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * ENOENT from the file stat.) 1882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = fstat(fd, &fdStat); 1902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0) { 191c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Can't stat open file '%s'", cacheFileName); 19260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("DexOpt: unlocking cache file %s", cacheFileName); 1932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto close_fail; 1942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 1952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = stat(cacheFileName, &fileStat); 1962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0 || 1972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden fdStat.st_dev != fileStat.st_dev || fdStat.st_ino != fileStat.st_ino) 1982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 199062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("DexOpt: our open cache file is stale; sleeping and retrying"); 20060fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("DexOpt: unlocking cache file %s", cacheFileName); 2012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flock(fd, LOCK_UN); 2022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden close(fd); 2032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden usleep(250 * 1000); /* if something is hosed, don't peg machine */ 2042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto retry; 2052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 2072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 2082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * We have the correct file open and locked. If the file size is zero, 2092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * then it was just created by us, and we want to fill in some fields 2102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * in the "opt" header and set "*pNewFile". Otherwise, we want to 2112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * verify that the fields in the header match our expectations, and 2122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * reset the file if they don't. 2132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 2142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (fdStat.st_size == 0) { 2152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (readOnly) { 216e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("DexOpt: file has zero length and isn't writable"); 2172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto close_fail; 2182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cc = dexOptCreateEmptyHeader(fd); 2202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (cc != 0) 2212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto close_fail; 2222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden *pNewFile = true; 22392c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: successfully initialized new cache file"); 2242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 2252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bool expectVerify, expectOpt; 2262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 227d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden if (gDvm.classVerifyMode == VERIFY_MODE_NONE) { 2282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify = false; 229d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) { 2302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify = !isBootstrap; 231d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ { 2322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify = true; 233d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } 2342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 235d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) { 2362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectOpt = false; 237d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED || 238d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden gDvm.dexOptMode == OPTIMIZE_MODE_FULL) { 2392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectOpt = expectVerify; 240d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ { 2412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectOpt = true; 242d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden } 2432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 24492c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("checking deps, expecting vfy=%d opt=%d", 2452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify, expectOpt); 2462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 2472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!dvmCheckOptHeaderAndDependencies(fd, true, modWhen, crc, 2482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden expectVerify, expectOpt)) 2492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 2502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (readOnly) { 2512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 2522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * We could unlink and rewrite the file if we own it or 2532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the "sticky" bit isn't set on the directory. However, 2542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * we're not able to truncate it, which spoils things. So, 2552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * give up now. 2562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 2572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (createIfMissing) { 258e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Cached DEX '%s' (%s) is stale and not writable", 2592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden fileName, cacheFileName); 2602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto close_fail; 2622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 2642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 2652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * If we truncate the existing file before unlinking it, any 2662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * process that has it mapped will fail when it tries to touch 2672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the pages. 2682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This is very important. The zygote process will have the 2702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * boot DEX files (core, framework, etc.) mapped early. If 2712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * (say) core.dex gets updated, and somebody launches an app 2722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * that uses App.dex, then App.dex gets reoptimized because it's 2732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * dependent upon the boot classes. However, dexopt will be 2742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * using the *new* core.dex to do the optimizations, while the 2752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * app will actually be running against the *old* core.dex 2762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * because it starts from zygote. 2772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 2782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Even without zygote, it's still possible for a class loader 2792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * to pull in an APK that was optimized against an older set 2802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * of DEX files. We must ensure that everything fails when a 2812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * boot DEX gets updated, and for general "why aren't my 2822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * changes doing anything" purposes its best if we just make 2832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * everything crash when a DEX they're using gets updated. 2842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 285062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("ODEX file is stale or bad; removing and retrying (%s)", 286e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden cacheFileName); 2872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (ftruncate(fd, 0) != 0) { 288e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Warning: unable to truncate cache file '%s': %s", 2892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cacheFileName, strerror(errno)); 2902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* keep going */ 2912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 2922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (unlink(cacheFileName) != 0) { 293e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Warning: unable to remove cache file '%s': %d %s", 2942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cacheFileName, errno, strerror(errno)); 2952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* keep going; permission failure should probably be fatal */ 2962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 29760fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("DexOpt: unlocking cache file %s", cacheFileName); 2982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flock(fd, LOCK_UN); 2992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden close(fd); 3002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto retry; 3012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 30292c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: good deps in cache file"); 3032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 3042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 3052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(fd >= 0); 3072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return fd; 3082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenclose_fail: 3102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flock(fd, LOCK_UN); 3112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden close(fd); 3122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return -1; 3132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 3142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 3162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Unlock the file descriptor. 3172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 3182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Returns "true" on success. 3192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 3202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbool dvmUnlockCachedDexFile(int fd) 3212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 32260fc806b679a3655c228b4093058c59941a49cfeDan Bornstein LOGVV("DexOpt: unlocking cache file fd=%d", fd); 3232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return (flock(fd, LOCK_UN) == 0); 3242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 3252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 3282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Given a descriptor for a file with DEX data in it, produce an 3292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * optimized version. 3302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 3312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * The file pointed to by "fd" is expected to be a locked shared resource 3322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * (or private); we make no efforts to enforce multi-process correctness 3332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * here. 3342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 3352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * "fileName" is only used for debug output. "modWhen" and "crc" are stored 3362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * in the dependency set. 3372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 3382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * The "isBootstrap" flag determines how the optimizer and verifier handle 3392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * package-scope access checks. When optimizing, we only load the bootstrap 3402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * class DEX files and the target DEX, so the flag determines whether the 3412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * target DEX classes are given a (synthetic) non-NULL classLoader pointer. 3422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This only really matters if the target DEX contains classes that claim to 3432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * be in the same package as bootstrap classes. 3442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 3452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * The optimizer will need to load every class in the target DEX file. 3462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This is generally undesirable, so we start a subprocess to do the 3472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * work and wait for it to complete. 3482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 3492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Returns "true" on success. All data will have been written to "fd". 3502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 3512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbool dvmOptimizeDexFile(int fd, off_t dexOffset, long dexLength, 3522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const char* fileName, u4 modWhen, u4 crc, bool isBootstrap) 3532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 3542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const char* lastPart = strrchr(fileName, '/'); 3552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (lastPart != NULL) 3562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lastPart++; 3572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden else 3582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lastPart = fileName; 3592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 360062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("DexOpt: --- BEGIN '%s' (bootstrap=%d) ---", lastPart, isBootstrap); 3612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pid_t pid; 3632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 3652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This could happen if something in our bootclasspath, which we thought 3662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * was all optimized, got rejected. 3672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 3682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.optimizing) { 369e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Rejecting recursive optimization attempt on '%s'", fileName); 3702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 3712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 3722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pid = fork(); 3742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (pid == 0) { 3752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const int kUseValgrind = 0; 3762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const char* kDexOptBin = "/bin/dexopt"; 3772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const char* kValgrinder = "/usr/bin/valgrind"; 3782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const int kFixedArgCount = 10; 3792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const int kValgrindArgCount = 5; 3802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden static const int kMaxIntLen = 12; // '-'+10dig+'\0' -OR- 0x+8dig 3812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int bcpSize = dvmGetBootPathSize(); 3822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int argc = kFixedArgCount + bcpSize 3832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden + (kValgrindArgCount * kUseValgrind); 3841813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro const char* argv[argc+1]; // last entry is NULL 3852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden char values[argc][kMaxIntLen]; 3862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden char* execFile; 3871813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro const char* androidRoot; 3882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int flags; 3892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* change process groups, so we don't clash with ProcessManager */ 3912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden setpgid(0, 0); 3922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 3932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* full path to optimizer */ 3942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden androidRoot = getenv("ANDROID_ROOT"); 3952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (androidRoot == NULL) { 396e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("ANDROID_ROOT not set, defaulting to /system"); 3972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden androidRoot = "/system"; 3982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 39963cd4b08e623242066c63563bad3a9f414a2bd2dAndy McFadden execFile = (char*)alloca(strlen(androidRoot) + strlen(kDexOptBin) + 1); 4002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden strcpy(execFile, androidRoot); 4012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden strcat(execFile, kDexOptBin); 4022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 4042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Create arg vector. 4052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 4062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int curArg = 0; 4072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (kUseValgrind) { 4092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* probably shouldn't ship the hard-coded path */ 4102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = (char*)kValgrinder; 4112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--tool=memcheck"; 4122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--leak-check=yes"; // check for leaks too 4132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--leak-resolution=med"; // increase from 2 to 4 4142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--num-callers=16"; // default is 12 4152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(curArg == kValgrindArgCount); 4162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = execFile; 4182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = "--dex"; 4202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[2], "%d", DALVIK_VM_BUILD); 4222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[2]; 4232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[3], "%d", fd); 4252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[3]; 4262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[4], "%d", (int) dexOffset); 4282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[4]; 4292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[5], "%d", (int) dexLength); 4312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[5]; 4322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = (char*)fileName; 4342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[7], "%d", (int) modWhen); 4362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[7]; 4372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[8], "%d", (int) crc); 4392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[8]; 4402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags = 0; 4422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.dexOptMode != OPTIMIZE_MODE_NONE) { 4432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_OPT_ENABLED; 4442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL) 4452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_OPT_ALL; 4462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.classVerifyMode != VERIFY_MODE_NONE) { 4482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_VERIFY_ENABLED; 4492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.classVerifyMode == VERIFY_MODE_ALL) 4502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_VERIFY_ALL; 4512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (isBootstrap) 4532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden flags |= DEXOPT_IS_BOOTSTRAP; 4542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.generateRegisterMaps) 455d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden flags |= DEXOPT_GEN_REGISTER_MAPS; 4562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden sprintf(values[9], "%d", flags); 4572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = values[9]; 4582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(((!kUseValgrind && curArg == kFixedArgCount) || 4602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ((kUseValgrind && curArg == kFixedArgCount+kValgrindArgCount)))); 4612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ClassPathEntry* cpe; 4632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 4642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg++] = cpe->fileName; 4652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(curArg == argc); 4672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden argv[curArg] = NULL; 4692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (kUseValgrind) 4711813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro execv(kValgrinder, const_cast<char**>(argv)); 4722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden else 4731813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro execv(execFile, const_cast<char**>(argv)); 4742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 475c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("execv '%s'%s failed: %s", execFile, 4762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden kUseValgrind ? " [valgrind]" : "", strerror(errno)); 4772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden exit(1); 4782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 47992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: waiting for verify+opt, pid=%d", (int) pid); 4802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int status; 4812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pid_t gotPid; 4822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 4832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 4842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Wait for the optimization process to finish. We go into VMWAIT 4852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * mode here so GC suspension won't have to wait for us. 4862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 4871813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro ThreadStatus oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT); 4882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden while (true) { 4892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden gotPid = waitpid(pid, &status, 0); 4902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gotPid == -1 && errno == EINTR) { 491062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("waitpid interrupted, retrying"); 4922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 4932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden break; 4942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 4962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmChangeStatus(NULL, oldStatus); 4972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gotPid != pid) { 498c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("waitpid failed: wanted %d, got %d: %s", 4992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (int) pid, (int) gotPid, strerror(errno)); 5002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 5012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 504062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("DexOpt: --- END '%s' (success) ---", lastPart); 5052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return true; 5062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 507e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("DexOpt: --- END '%s' --- status=0x%04x, process failed", 5082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lastPart, status); 5092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 5102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 5132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 515cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Do the actual optimization. This is executed in the dexopt process. 5162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 5172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * For best use of disk/memory, we want to extract once and perform 5182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * optimizations in place. If the file has to expand or contract 5192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * to match local structure padding/alignment expectations, we want 5202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * to do the rewrite as part of the extract, rather than extracting 5212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * into a temp file and slurping it back out. (The structure alignment 5222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * is currently correct for all platforms, and this isn't expected to 5232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * change, so we should be okay with having it already extracted.) 5242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 5252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Returns "true" on success. 5262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 5272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbool dvmContinueOptimization(int fd, off_t dexOffset, long dexLength, 5282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const char* fileName, u4 modWhen, u4 crc, bool isBootstrap) 5292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 5302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DexClassLookup* pClassLookup = NULL; 5312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden RegisterMapBuilder* pRegMapBuilder = NULL; 5322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 533cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden assert(gDvm.optimizing); 5342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 53592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Continuing optimization (%s, isb=%d)", fileName, isBootstrap); 5362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(dexOffset >= 0); 5382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* quick test so we don't blow up on empty file */ 5402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (dexLength < (int) sizeof(DexHeader)) { 541c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("too small to be DEX"); 5422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 5432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (dexOffset < (int) sizeof(DexOptHeader)) { 545c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("not enough room for opt header"); 5462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 5472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bool result = false; 5502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 5522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Drop this into a global so we don't have to pass it around. We could 5532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * also add a field to DexFile, but since it only pertains to DEX 5542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * creation that probably doesn't make sense. 5552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 5562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden gDvm.optimizingBootstrapClass = isBootstrap; 5572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 5582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 5592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 5602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Map the entire file (so we don't have to worry about page 5612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * alignment). The expectation is that the output file contains 5622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * our DEX data plus room for a small header. 5632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 5642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bool success; 5652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden void* mapAddr; 5662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden mapAddr = mmap(NULL, dexOffset + dexLength, PROT_READ|PROT_WRITE, 5672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden MAP_SHARED, fd, 0); 5682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (mapAddr == MAP_FAILED) { 569c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("unable to mmap DEX cache: %s", strerror(errno)); 5702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 5712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 5722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 57357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden bool doVerify, doOpt; 57457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden if (gDvm.classVerifyMode == VERIFY_MODE_NONE) { 57557fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden doVerify = false; 57657fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } else if (gDvm.classVerifyMode == VERIFY_MODE_REMOTE) { 57757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden doVerify = !gDvm.optimizingBootstrapClass; 57857fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } else /*if (gDvm.classVerifyMode == VERIFY_MODE_ALL)*/ { 57957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden doVerify = true; 58057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } 58157fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden 58257fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden if (gDvm.dexOptMode == OPTIMIZE_MODE_NONE) { 58357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden doOpt = false; 58457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } else if (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED || 58557fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden gDvm.dexOptMode == OPTIMIZE_MODE_FULL) { 58657fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden doOpt = doVerify; 58757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } else /*if (gDvm.dexOptMode == OPTIMIZE_MODE_ALL)*/ { 58857fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden doOpt = true; 58957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } 59057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden 5912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 5922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Rewrite the file. Byte reordering, structure realigning, 5932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * class verification, and bytecode optimization are all performed 5942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * here. 5952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 5962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * In theory the file could change size and bits could shift around. 5972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * In practice this would be annoying to deal with, so the file 5982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * layout is designed so that it can always be rewritten in place. 5992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 60057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * This creates the class lookup table as part of doing the processing. 6012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 602cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden success = rewriteDex(((u1*) mapAddr) + dexOffset, dexLength, 60357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden doVerify, doOpt, &pClassLookup, NULL); 6042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (success) { 6062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DvmDex* pDvmDex = NULL; 6072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u1* dexAddr = ((u1*) mapAddr) + dexOffset; 6082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (dvmDexFileOpenPartial(dexAddr, dexLength, &pDvmDex) != 0) { 610c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unable to create DexFile"); 6112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden success = false; 6122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } else { 6132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 614cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * If configured to do so, generate register map output 615cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * for all verified classes. The register maps were 616cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * generated during verification, and will now be serialized. 6172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 6182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (gDvm.generateRegisterMaps) { 6192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pRegMapBuilder = dvmGenerateRegisterMaps(pDvmDex); 6202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (pRegMapBuilder == NULL) { 621c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Failed generating register maps"); 6222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden success = false; 6232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DexHeader* pHeader = (DexHeader*)pDvmDex->pHeader; 6272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden updateChecksum(dexAddr, dexLength, pHeader); 6282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmDexFileFree(pDvmDex); 6302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* unmap the read-write version, forcing writes to disk */ 6342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (msync(mapAddr, dexOffset + dexLength, MS_SYNC) != 0) { 635e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("msync failed: %s", strerror(errno)); 6362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // weird, but keep going 6372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#if 1 6392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 6402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * This causes clean shutdown to fail, because we have loaded classes 6412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * that point into it. For the optimizer this isn't a problem, 6422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * because it's more efficient for the process to simply exit. 6432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Exclude this code when doing clean shutdown for valgrind. 6442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 6452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (munmap(mapAddr, dexOffset + dexLength) != 0) { 646c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("munmap failed: %s", strerror(errno)); 6472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 6482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#endif 6502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!success) 6522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 6532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* get start offset, and adjust deps start for 64-bit alignment */ 656e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein off_t depsOffset, optOffset, endOffset, adjOffset; 657e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein int depsLength, optLength; 6582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 optChecksum; 6592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden depsOffset = lseek(fd, 0, SEEK_END); 6612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (depsOffset < 0) { 662c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("lseek to EOF failed: %s", strerror(errno)); 6632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 6642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden adjOffset = (depsOffset + 7) & ~(0x07); 6662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (adjOffset != depsOffset) { 66792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Adjusting deps start from %d to %d", 6682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (int) depsOffset, (int) adjOffset); 6692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden depsOffset = adjOffset; 6702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lseek(fd, depsOffset, SEEK_SET); 6712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 6742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Append the dependency list. 6752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 6762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (writeDependencies(fd, modWhen, crc) != 0) { 677e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Failed writing dependencies"); 6782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 6792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 681e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein /* compute deps length, then adjust opt start for 64-bit alignment */ 682e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optOffset = lseek(fd, 0, SEEK_END); 683e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein depsLength = optOffset - depsOffset; 6842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 685e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein adjOffset = (optOffset + 7) & ~(0x07); 686e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein if (adjOffset != optOffset) { 68792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Adjusting opt start from %d to %d", 688e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein (int) optOffset, (int) adjOffset); 689e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optOffset = adjOffset; 690e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein lseek(fd, optOffset, SEEK_SET); 6912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 6922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 6932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 694e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Append any optimized pre-computed data structures. 6952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 696d394371bd84bacc51e96e2d2eacb8549d9110b1eDan Bornstein if (!writeOptData(fd, pClassLookup, pRegMapBuilder)) { 697e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("Failed writing opt data"); 6982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 6992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 7002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 7012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden endOffset = lseek(fd, 0, SEEK_END); 702e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optLength = endOffset - optOffset; 7032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 704e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein /* compute checksum from start of deps to end of opt area */ 7052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!computeFileChecksum(fd, depsOffset, 706e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein (optOffset+optLength) - depsOffset, &optChecksum)) 7072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 7082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 7092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 7102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 7112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 7122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Output the "opt" header with all values filled in and a correct 7132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * magic number. 7142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 7152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DexOptHeader optHdr; 7162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memset(&optHdr, 0xff, sizeof(optHdr)); 7172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memcpy(optHdr.magic, DEX_OPT_MAGIC, 4); 7182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memcpy(optHdr.magic+4, DEX_OPT_MAGIC_VERS, 4); 7192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.dexOffset = (u4) dexOffset; 7202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.dexLength = (u4) dexLength; 7212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.depsOffset = (u4) depsOffset; 7222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.depsLength = (u4) depsLength; 723e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optHdr.optOffset = (u4) optOffset; 724e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein optHdr.optLength = (u4) optLength; 72557fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden#if __BYTE_ORDER != __LITTLE_ENDIAN 72657fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden optHdr.flags = DEX_OPT_FLAG_BIG; 72757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden#else 72857fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden optHdr.flags = 0; 72957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden#endif 7302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.checksum = optChecksum; 7312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 732c650d2beb66896c0cf51f737d7a39476630dd142Andy McFadden fsync(fd); /* ensure previous writes go before header is written */ 733c650d2beb66896c0cf51f737d7a39476630dd142Andy McFadden 7342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lseek(fd, 0, SEEK_SET); 73564896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden if (sysWriteFully(fd, &optHdr, sizeof(optHdr), "DexOpt opt header") != 0) 7362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 7372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 73892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Successfully wrote DEX header"); 7392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden result = true; 7402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 7412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden //dvmRegisterMapDumpStats(); 7422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 7432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbail: 7442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmFreeRegisterMapBuilder(pRegMapBuilder); 7452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden free(pClassLookup); 7462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return result; 7472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 7482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 74957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden/* 75057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * Prepare an in-memory DEX file. 75157fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * 75257fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * The data was presented to the VM as a byte array rather than a file. 75357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * We want to do the same basic set of operations, but we can just leave 75457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * them in memory instead of writing them out to a cached optimized DEX file. 75557fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden */ 75657fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFaddenbool dvmPrepareDexInMemory(u1* addr, size_t len, DvmDex** ppDvmDex) 75757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden{ 75857fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden DexClassLookup* pClassLookup = NULL; 75957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden 76057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden /* 76157fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * Byte-swap, realign, verify basic DEX file structure. 76257fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * 76357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * We could load + verify + optimize here as well, but that's probably 76457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * not desirable. 76557fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * 76657fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * (The bulk-verification code is currently only setting the DEX 76757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * file's "verified" flag, not updating the ClassObject. This would 76857fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * also need to be changed, or we will try to verify the class twice, 76957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * and possibly reject it when optimized opcodes are encountered.) 77057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden */ 77157fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden if (!rewriteDex(addr, len, false, false, &pClassLookup, ppDvmDex)) { 77257fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden return false; 77357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } 77457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden 77557fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden (*ppDvmDex)->pDexFile->pClassLookup = pClassLookup; 77657fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden 77757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden return true; 77857fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden} 7792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 7802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 781cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Perform in-place rewrites on a memory-mapped DEX file. 782cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 78357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * If this is called from a short-lived child process (dexopt), we can 78457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * go nutty with loading classes and allocating memory. When it's 78557fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * called to prepare classes provided in a byte array, we may want to 78657fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * be more conservative. 78757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * 78857fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * If "ppClassLookup" is non-NULL, a pointer to a newly-allocated 78957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * DexClassLookup will be returned on success. 79057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * 79157fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * If "ppDvmDex" is non-NULL, a newly-allocated DvmDex struct will be 79257fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * returned on success. 793cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 79457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFaddenstatic bool rewriteDex(u1* addr, int len, bool doVerify, bool doOpt, 79557fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden DexClassLookup** ppClassLookup, DvmDex** ppDvmDex) 796cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden{ 79757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden DexClassLookup* pClassLookup = NULL; 798cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u8 prepWhen, loadWhen, verifyOptWhen; 799cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden DvmDex* pDvmDex = NULL; 800cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden bool result = false; 8011813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro const char* msgStr = "???"; 802cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 803cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* if the DEX is in the wrong byte order, swap it now */ 8044b0750e8df91220690bb417f45d7ae8b7851b220Dan Bornstein if (dexSwapAndVerify(addr, len) != 0) 805cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 806cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 807cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 808cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Now that the DEX file can be read directly, create a DexFile struct 809cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * for it. 810cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 811cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (dvmDexFileOpenPartial(addr, len, &pDvmDex) != 0) { 812c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unable to create DexFile"); 813cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 814cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 815cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 816cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 817cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Create the class lookup table. This will eventually be appended 818cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * to the end of the .odex. 81957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * 82057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * We create a temporary link from the DexFile for the benefit of 82157fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * class loading, below. 822cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 82357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden pClassLookup = dexCreateClassLookup(pDvmDex->pDexFile); 82457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden if (pClassLookup == NULL) 825cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 82657fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden pDvmDex->pDexFile->pClassLookup = pClassLookup; 827cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 828cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 829cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * If we're not going to attempt to verify or optimize the classes, 830cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * there's no value in loading them, so bail out early. 831cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 832cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (!doVerify && !doOpt) { 833cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden result = true; 834cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 835cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 836cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 837cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden prepWhen = dvmGetRelativeTimeUsec(); 838cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 839cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 840cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Load all classes found in this DEX file. If they fail to load for 841cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * some reason, they won't get verified (which is as it should be). 842cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 843cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (!loadAllClasses(pDvmDex)) 844cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden goto bail; 845cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden loadWhen = dvmGetRelativeTimeUsec(); 846cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 847cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 84865a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * Create a data structure for use by the bytecode optimizer. 84965a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * We need to look up methods in a few classes, so this may cause 85065a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * a bit of class loading. We usually do this during VM init, but 85165a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * for dexopt on core.jar the order of operations gets a bit tricky, 85265a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden * so we defer it to here. 85365a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden */ 85465a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden if (!dvmCreateInlineSubsTable()) 85565a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden goto bail; 85665a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden 85765a54dc66d2c7b6e16fc24a6ce66e50483620745Andy McFadden /* 858cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Verify and optimize all classes in the DEX file (command-line 859cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * options permitting). 860cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 861cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * This is best-effort, so there's really no way for dexopt to 862cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * fail at this point. 863cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 864cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden verifyAndOptimizeClasses(pDvmDex->pDexFile, doVerify, doOpt); 865cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden verifyOptWhen = dvmGetRelativeTimeUsec(); 866cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 867cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (doVerify && doOpt) 868cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden msgStr = "verify+opt"; 869cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden else if (doVerify) 870cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden msgStr = "verify"; 871cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden else if (doOpt) 872cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden msgStr = "opt"; 8736ad3f100edffe51b2d4592dce893e1e2bb566161jeffhao ALOGD("DexOpt: load %dms, %s %dms, %d bytes", 874cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden (int) (loadWhen - prepWhen) / 1000, 875cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden msgStr, 8766ad3f100edffe51b2d4592dce893e1e2bb566161jeffhao (int) (verifyOptWhen - loadWhen) / 1000, 8776ad3f100edffe51b2d4592dce893e1e2bb566161jeffhao gDvm.pBootLoaderAlloc->curOffset); 878cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 879cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden result = true; 880cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 881cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenbail: 88257fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden /* 88357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * On success, return the pieces that the caller asked for. 88457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden */ 885a78b1255ad1ce8dcacad21338d4f88db4231c4cdAndy McFadden 886a78b1255ad1ce8dcacad21338d4f88db4231c4cdAndy McFadden if (pDvmDex != NULL) { 887a78b1255ad1ce8dcacad21338d4f88db4231c4cdAndy McFadden /* break link between the two */ 888a78b1255ad1ce8dcacad21338d4f88db4231c4cdAndy McFadden pDvmDex->pDexFile->pClassLookup = NULL; 889a78b1255ad1ce8dcacad21338d4f88db4231c4cdAndy McFadden } 890a78b1255ad1ce8dcacad21338d4f88db4231c4cdAndy McFadden 89157fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden if (ppDvmDex == NULL || !result) { 89257fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden dvmDexFileFree(pDvmDex); 89357fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } else { 89457fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden *ppDvmDex = pDvmDex; 89557fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } 89657fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden 89757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden if (ppClassLookup == NULL || !result) { 89857fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden free(pClassLookup); 89957fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } else { 90057fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden *ppClassLookup = pClassLookup; 90157fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden } 90257fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden 903cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden return result; 904cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden} 905cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 906cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden/* 907cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Try to load all classes in the specified DEX. If they have some sort 908cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * of broken dependency, e.g. their superclass lives in a different DEX 909cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * that wasn't previously loaded into the bootstrap class path, loading 910cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * will fail. This is the desired behavior. 911cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 912cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * We have no notion of class loader at this point, so we load all of 913cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * the classes with the bootstrap class loader. It turns out this has 914cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * exactly the behavior we want, and has no ill side effects because we're 915cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * running in a separate process and anything we load here will be forgotten. 916cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 917cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * We set the CLASS_MULTIPLE_DEFS flag here if we see multiple definitions. 918cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * This works because we only call here as part of optimization / pre-verify, 919cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * not during verification as part of loading a class into a running VM. 920cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * 921cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * This returns "false" if the world is too screwed up to do anything 922cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * useful at all. 923cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 924cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic bool loadAllClasses(DvmDex* pDvmDex) 925cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden{ 926cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u4 count = pDvmDex->pDexFile->pHeader->classDefsSize; 927cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u4 idx; 928cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden int loaded = 0; 929cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 93092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: +++ trying to load %d classes", count); 931cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 932cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden dvmSetBootPathExtraDex(pDvmDex); 933cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 934cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 9358521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * At this point, it is safe -- and necessary! -- to look up the 9368521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * VM's required classes and members, even when what we are in the 9378521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * process of processing is the core library that defines these 9384b5fa2e50860015beebcc5fc3a33265b266d6d34Dan Bornstein * classes itself. (The reason it is necessary is that in the act 9394b5fa2e50860015beebcc5fc3a33265b266d6d34Dan Bornstein * of initializing the class Class, below, the system will end up 9404b5fa2e50860015beebcc5fc3a33265b266d6d34Dan Bornstein * referring to many of the class references that got set up by 9414b5fa2e50860015beebcc5fc3a33265b266d6d34Dan Bornstein * this call.) 9428521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein */ 9434b5fa2e50860015beebcc5fc3a33265b266d6d34Dan Bornstein if (!dvmFindRequiredClassesAndMembers()) { 9448521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein return false; 9458521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein } 9468521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein 9478521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein /* 9488521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * We have some circularity issues with Class and Object that are 9498521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * most easily avoided by ensuring that Object is never the first 9508521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * thing we try to find-and-initialize. The call to 9518521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * dvmFindSystemClass() here takes care of that situation. (We 9528521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * only need to do this when loading classes from the DEX file 9538521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * that contains Object, and only when Object comes first in the 9548521311b4e55847c650a87933d5a3f04618e4e69Dan Bornstein * list, but it costs very little to do it in all cases.) 955cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 9563111b0c80ca3f90e966371cbab606ac38ed17cadDan Bornstein if (!dvmInitClass(gDvm.classJavaLangClass)) { 957c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("ERROR: failed to initialize the class Class!"); 958cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden return false; 959cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 960cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 961cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden for (idx = 0; idx < count; idx++) { 962cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const DexClassDef* pClassDef; 963cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const char* classDescriptor; 964cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden ClassObject* newClass; 965cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 966cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden pClassDef = dexGetClassDef(pDvmDex->pDexFile, idx); 967cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor = 968cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden dexStringByTypeIdx(pDvmDex->pDexFile, pClassDef->classIdx); 969cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 97092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ loading '%s'", classDescriptor); 971cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden //newClass = dvmDefineClass(pDexFile, classDescriptor, 972cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden // NULL); 973cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden newClass = dvmFindSystemClassNoInit(classDescriptor); 974cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (newClass == NULL) { 97592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: failed loading '%s'", classDescriptor); 976cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden dvmClearOptException(dvmThreadSelf()); 977cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else if (newClass->pDvmDex != pDvmDex) { 978cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 979cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * We don't load the new one, and we tag the first one found 980cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * with the "multiple def" flag so the resolver doesn't try 981cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * to make it available. 982cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 983062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("DexOpt: '%s' has an earlier definition; blocking out", 984cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor); 985cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden SET_CLASS_FLAG(newClass, CLASS_MULTIPLE_DEFS); 986cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else { 987cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden loaded++; 988cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 989cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 99092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: +++ successfully loaded %d classes", loaded); 991cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 992cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden dvmSetBootPathExtraDex(NULL); 993cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden return true; 994cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden} 995cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 996cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden/* 997cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Verify and/or optimize all classes that were successfully loaded from 998cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * this DEX file. 999cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 1000cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic void verifyAndOptimizeClasses(DexFile* pDexFile, bool doVerify, 1001cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden bool doOpt) 1002cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden{ 1003cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u4 count = pDexFile->pHeader->classDefsSize; 1004cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden u4 idx; 1005cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1006cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden for (idx = 0; idx < count; idx++) { 1007cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const DexClassDef* pClassDef; 1008cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const char* classDescriptor; 1009cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden ClassObject* clazz; 1010cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1011cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden pClassDef = dexGetClassDef(pDexFile, idx); 1012cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); 1013cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1014cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* all classes are loaded into the bootstrap class loader */ 1015cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden clazz = dvmLookupClass(classDescriptor, NULL, false); 1016cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (clazz != NULL) { 1017cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden verifyAndOptimizeClass(pDexFile, clazz, pClassDef, doVerify, doOpt); 1018cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1019cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else { 1020cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden // TODO: log when in verbose mode 102192c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: not optimizing unavailable class '%s'", 1022cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor); 1023cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 1024cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 1025cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1026470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden#ifdef VERIFIER_STATS 10274308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("Verifier stats:"); 10284308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" methods examined : %u", gDvm.verifierStats.methodsExamined); 10294308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" monitor-enter methods : %u", gDvm.verifierStats.monEnterMethods); 10304308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" instructions examined : %u", gDvm.verifierStats.instrsExamined); 10314308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" instructions re-examined: %u", gDvm.verifierStats.instrsReexamined); 10324308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" copying of register sets: %u", gDvm.verifierStats.copyRegCount); 10334308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" merging of register sets: %u", gDvm.verifierStats.mergeRegCount); 10344308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" ...that caused changes : %u", gDvm.verifierStats.mergeRegChanged); 10354308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" uninit searches : %u", gDvm.verifierStats.uninitSearches); 10364308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI(" max memory required : %u", gDvm.verifierStats.biggestAlloc); 1037470cbbbe39cffd9b1cf52562048c60be543004c6Andy McFadden#endif 1038cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden} 1039cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1040cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden/* 1041cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * Verify and/or optimize a specific class. 1042cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 1043cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFaddenstatic void verifyAndOptimizeClass(DexFile* pDexFile, ClassObject* clazz, 1044cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const DexClassDef* pClassDef, bool doVerify, bool doOpt) 1045cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden{ 1046cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden const char* classDescriptor; 1047cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden bool verified = false; 1048cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 10493f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden if (clazz->pDvmDex->pDexFile != pDexFile) { 10503f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden /* 10513f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * The current DEX file defined a class that is also present in the 10523f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * bootstrap class path. The class loader favored the bootstrap 10533f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * version, which means that we have a pointer to a class that is 10543f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * (a) not the one we want to examine, and (b) mapped read-only, 10553f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * so we will seg fault if we try to rewrite instructions inside it. 10563f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden */ 1057062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("DexOpt: not verifying/optimizing '%s': multiple definitions", 10583f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden clazz->descriptor); 10593f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden return; 10603f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden } 10613f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden 1062cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx); 1063cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1064cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* 1065cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden * First, try to verify it. 1066cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden */ 1067cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (doVerify) { 10683f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden if (dvmVerifyClass(clazz)) { 10693f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden /* 10703f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * Set the "is preverified" flag in the DexClassDef. We 10713f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * do it here, rather than in the ClassObject structure, 10723f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden * because the DexClassDef is part of the odex file. 10733f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden */ 10743f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden assert((clazz->accessFlags & JAVA_FLAGS_MASK) == 10753f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden pClassDef->accessFlags); 10763f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISPREVERIFIED; 10773f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden verified = true; 1078cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else { 10793f4b63f47f50f200538e83fa3fac06947afa08b4Andy McFadden // TODO: log when in verbose mode 108092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: '%s' failed verification", classDescriptor); 1081cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 1082cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 1083cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1084cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden if (doOpt) { 1085d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden bool needVerify = (gDvm.dexOptMode == OPTIMIZE_MODE_VERIFIED || 1086d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden gDvm.dexOptMode == OPTIMIZE_MODE_FULL); 1087d18fcbcee7115ff99673222650fda0f7e982c60aAndy McFadden if (!verified && needVerify) { 108892c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: not optimizing '%s': not verified", 1089cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden classDescriptor); 1090cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } else { 1091fb119e6cf8b47d53f024cae889487a17eacbf19fAndy McFadden dvmOptimizeClass(clazz, false); 1092cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1093cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden /* set the flag whether or not we actually changed anything */ 1094cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden ((DexClassDef*)pClassDef)->accessFlags |= CLASS_ISOPTIMIZED; 1095cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 1096cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden } 1097cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden} 1098cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1099cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden 1100cb3c542b8712b7ef005aabc4b8139c667afc7a9dAndy McFadden/* 11012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Get the cache file name from a ClassPathEntry. 11022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 11032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic const char* getCacheFileName(const ClassPathEntry* cpe) 11042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 11052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden switch (cpe->kind) { 11062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden case kCpeJar: 11072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return dvmGetJarFileCacheFileName((JarFile*) cpe->ptr); 11082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden case kCpeDex: 11092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return dvmGetRawDexFileCacheFileName((RawDexFile*) cpe->ptr); 11102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden default: 1111c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DexOpt: unexpected cpe kind %d", cpe->kind); 11122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmAbort(); 11132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return NULL; 11142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 11162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 11182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Get the SHA-1 signature. 11192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 11202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic const u1* getSignature(const ClassPathEntry* cpe) 11212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 11222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DvmDex* pDvmDex; 11232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden switch (cpe->kind) { 11252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden case kCpeJar: 11262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pDvmDex = dvmGetJarFileDex((JarFile*) cpe->ptr); 11272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden break; 11282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden case kCpeDex: 11292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pDvmDex = dvmGetRawDexFileDex((RawDexFile*) cpe->ptr); 11302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden break; 11312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden default: 1132c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("unexpected cpe kind %d", cpe->kind); 11332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmAbort(); 11342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pDvmDex = NULL; // make gcc happy 11352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(pDvmDex != NULL); 11382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return pDvmDex->pDexFile->pHeader->signature; 11392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 11402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 11432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Dependency layout: 11442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b Source file modification time, in seconds since 1970 UTC 11452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b CRC-32 from Zip entry, or Adler32 from source DEX header 11462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b Dalvik VM build number 11472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b Number of dependency entries that follow 11482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Dependency entries: 11492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 4b Name length (including terminating null) 11502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * var Full path of cache entry (null terminated) 11512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 20b SHA-1 signature from source DEX file 11522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 11532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * If this changes, update DEX_OPT_MAGIC_VERS. 11542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 11552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic const size_t kMinDepSize = 4 * 4; 11568b31f73c2d72cfac18125f15bc69a74d3204389bJesse Wilsonstatic const size_t kMaxDepSize = 4 * 4 + 2048; // sanity check 11572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 11592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Read the "opt" header, verify it, then read the dependencies section 11602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * and verify that data as well. 11612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 11622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * If "sourceAvail" is "true", this will verify that "modWhen" and "crc" 11632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * match up with what is stored in the header. If they don't, we reject 11642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the file so that it can be recreated from the updated original. If 11652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * "sourceAvail" isn't set, e.g. for a .odex file, we ignore these arguments. 11662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 11672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * On successful return, the file will be seeked immediately past the 11682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * "opt" header. 11692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 11702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbool dvmCheckOptHeaderAndDependencies(int fd, bool sourceAvail, u4 modWhen, 11712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 crc, bool expectVerify, bool expectOpt) 11722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 11732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden DexOptHeader optHdr; 11742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u1* depData = NULL; 11752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const u1* magic; 11762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden off_t posn; 11772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int result = false; 11782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ssize_t actual; 11792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 11812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Start at the start. The "opt" header, when present, will always be 11822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * the first thing in the file. 11832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 11842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (lseek(fd, 0, SEEK_SET) != 0) { 1185c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DexOpt: failed to seek to start of file: %s", strerror(errno)); 11862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 11872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 11882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 11892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 11902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Read and do trivial verification on the opt header. The header is 11912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * always in host byte order. 11922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1193e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden actual = read(fd, &optHdr, sizeof(optHdr)); 1194e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden if (actual < 0) { 1195c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DexOpt: failed reading opt header: %s", strerror(errno)); 11962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 1197e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden } else if (actual != sizeof(optHdr)) { 1198c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DexOpt: failed reading opt header (got %d of %zd)", 1199e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden (int) actual, sizeof(optHdr)); 1200e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden goto bail; 12012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden magic = optHdr.magic; 1204e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden if (memcmp(magic, DEX_MAGIC, 4) == 0) { 1205e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden /* somebody probably pointed us at the wrong file */ 1206062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("DexOpt: expected optimized DEX, found unoptimized"); 1207e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden goto bail; 1208e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden } else if (memcmp(magic, DEX_OPT_MAGIC, 4) != 0) { 12092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* not a DEX file, or previous attempt was interrupted */ 1210062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("DexOpt: incorrect opt magic number (0x%02x %02x %02x %02x)", 12112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden magic[0], magic[1], magic[2], magic[3]); 12122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (memcmp(magic+4, DEX_OPT_MAGIC_VERS, 4) != 0) { 1215e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("DexOpt: stale opt version (0x%02x %02x %02x %02x)", 12162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden magic[4], magic[5], magic[6], magic[7]); 12172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (optHdr.depsLength < kMinDepSize || optHdr.depsLength > kMaxDepSize) { 1220e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("DexOpt: weird deps length %d, bailing", optHdr.depsLength); 12212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 12252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Do the header flags match up with what we want? 12262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 122757fd399d1265ec627d28a15b3d4b98e5f239ac88Andy McFadden * The only thing we really can't handle is incorrect byte ordering. 12282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 12291813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro { 12301813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro const u4 matchMask = DEX_OPT_FLAG_BIG; 12311813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro u4 expectedFlags = 0; 12322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#if __BYTE_ORDER != __LITTLE_ENDIAN 12331813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro expectedFlags |= DEX_OPT_FLAG_BIG; 12342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden#endif 12351813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro if ((expectedFlags & matchMask) != (optHdr.flags & matchMask)) { 12364308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("DexOpt: header flag mismatch (0x%02x vs 0x%02x, mask=0x%02x)", 12371813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro expectedFlags, optHdr.flags, matchMask); 12381813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro goto bail; 12391813ab265f691e93401c7307c0b34247842ab35eCarl Shapiro } 12402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden posn = lseek(fd, optHdr.depsOffset, SEEK_SET); 12432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (posn < 0) { 1244e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("DexOpt: seek to deps failed: %s", strerror(errno)); 12452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 12492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Read all of the dependency stuff into memory. 12502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 12512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden depData = (u1*) malloc(optHdr.depsLength); 12522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (depData == NULL) { 1253e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("DexOpt: unable to allocate %d bytes for deps", 12542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden optHdr.depsLength); 12552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden actual = read(fd, depData, optHdr.depsLength); 1258e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden if (actual < 0) { 1259e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("DexOpt: failed reading deps: %s", strerror(errno)); 1260e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden goto bail; 1261e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden } else if (actual != (ssize_t) optHdr.depsLength) { 1262e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("DexOpt: failed reading deps: got %d of %d", 1263e7ad112562af04d825fdd0d403deaf0ddd70a2eaAndy McFadden (int) actual, optHdr.depsLength); 12642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 12682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Verify simple items. 12692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 12702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const u1* ptr; 12712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 val; 12722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr = depData; 12742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val = read4LE(&ptr); 12752e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (sourceAvail && val != modWhen) { 12764308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("DexOpt: source file mod time mismatch (%08x vs %08x)", 12772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val, modWhen); 12782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val = read4LE(&ptr); 12812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (sourceAvail && val != crc) { 12824308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("DexOpt: source file CRC mismatch (%08x vs %08x)", val, crc); 12832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val = read4LE(&ptr); 12862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (val != DALVIK_VM_BUILD) { 1287062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block ALOGD("DexOpt: VM build version mismatch (%d vs %d)", 12882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden val, DALVIK_VM_BUILD); 12892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 12902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 12912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 12932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Verify dependencies on other cached DEX files. It must match 12942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * exactly with what is currently defined in the bootclasspath. 12952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 12962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ClassPathEntry* cpe; 12972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 numDeps; 12982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 12992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden numDeps = read4LE(&ptr); 130092c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ DexOpt: numDeps = %d", numDeps); 13012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 130232bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein const char* cacheFileName = 130332bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein dvmPathToAbsolutePortion(getCacheFileName(cpe)); 130432bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein assert(cacheFileName != NULL); /* guaranteed by Class.c */ 130532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein 13062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const u1* signature = getSignature(cpe); 13072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden size_t len = strlen(cacheFileName) +1; 13082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 storedStrLen; 13092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (numDeps == 0) { 13112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* more entries in bootclasspath than in deps list */ 13124308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("DexOpt: not all deps represented"); 13132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 13142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden storedStrLen = read4LE(&ptr); 13172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (len != storedStrLen || 13182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden strcmp(cacheFileName, (const char*) ptr) != 0) 13192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 13204308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("DexOpt: mismatch dep name: '%s' vs. '%s'", 13212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden cacheFileName, ptr); 13222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 13232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += storedStrLen; 13262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (memcmp(signature, ptr, kSHA1DigestLen) != 0) { 13284308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("DexOpt: mismatch dep signature for '%s'", cacheFileName); 13292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 13302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += kSHA1DigestLen; 13322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 133392c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("DexOpt: dep match on '%s'", cacheFileName); 13342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden numDeps--; 13362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (numDeps != 0) { 13392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* more entries in deps list than in classpath */ 13404308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block ALOGI("DexOpt: Some deps went away"); 13412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden goto bail; 13422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // consumed all data and no more? 13452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (ptr != depData + optHdr.depsLength) { 1346e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block ALOGW("DexOpt: Spurious dep data? %d vs %d", 13472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (int) (ptr - depData), optHdr.depsLength); 13482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(false); 13492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13512e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden result = true; 13522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenbail: 13542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden free(depData); 13552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return result; 13562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 13572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 13592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Write the dependency info to "fd" at the current file position. 13602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 13612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic int writeDependencies(int fd, u4 modWhen, u4 crc) 13622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 13632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u1* buf = NULL; 13642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int result = -1; 13652e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ssize_t bufLen; 13662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ClassPathEntry* cpe; 1367e3c01dac83e6eea7f82fe81ed89cfbdd9791dbc9Carl Shapiro int numDeps; 13682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 13702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Count up the number of completed entries in the bootclasspath. 13712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 13722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden numDeps = 0; 13732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bufLen = 0; 13742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 137532bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein const char* cacheFileName = 137632bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein dvmPathToAbsolutePortion(getCacheFileName(cpe)); 137732bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein assert(cacheFileName != NULL); /* guaranteed by Class.c */ 137832bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein 137992c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("+++ DexOpt: found dep '%s'", cacheFileName); 13802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden numDeps++; 13822e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bufLen += strlen(cacheFileName) +1; 13832e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 13842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden bufLen += 4*4 + numDeps * (4+kSHA1DigestLen); 13862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 1387fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro buf = (u1*)malloc(bufLen); 13882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(buf+0, modWhen); 13902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(buf+4, crc); 13912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(buf+8, DALVIK_VM_BUILD); 13922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(buf+12, numDeps); 13932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // TODO: do we want to add dvmGetInlineOpsTableLength() here? Won't 13952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // help us if somebody replaces an existing entry, but it'd catch 13962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden // additions/removals. 13972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 13982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u1* ptr = buf + 4*4; 13992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden for (cpe = gDvm.bootClassPath; cpe->ptr != NULL; cpe++) { 140032bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein const char* cacheFileName = 140132bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein dvmPathToAbsolutePortion(getCacheFileName(cpe)); 140232bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein assert(cacheFileName != NULL); /* guaranteed by Class.c */ 140332bc0787307ba57e92fa74c52da550e2ca22af7fDan Bornstein 14042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const u1* signature = getSignature(cpe); 14052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int len = strlen(cacheFileName) +1; 14062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (ptr + 4 + len + kSHA1DigestLen > buf + bufLen) { 1408c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("DexOpt: overran buffer"); 14092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden dvmAbort(); 14102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden set4LE(ptr, len); 14132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += 4; 14142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memcpy(ptr, cacheFileName, len); 14152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += len; 14162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden memcpy(ptr, signature, kSHA1DigestLen); 14172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ptr += kSHA1DigestLen; 14182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(ptr == buf + bufLen); 14212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 142264896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden result = sysWriteFully(fd, buf, bufLen, "DexOpt dep info"); 14232e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden free(buf); 14252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return result; 14262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 14272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 14302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Write a block of data in "chunk" format. 14312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 14322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * The chunk header fields are always in "native" byte order. If "size" 14332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * is not a multiple of 8 bytes, the data area is padded out. 14342e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 14352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic bool writeChunk(int fd, u4 type, const void* data, size_t size) 14362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 14372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden union { /* save a syscall by grouping these together */ 14382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden char raw[8]; 14392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden struct { 14402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 type; 14412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden u4 size; 14422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } ts; 14432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } header; 14442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert(sizeof(header) == 8); 14462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 144792c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("Writing chunk, type=%.4s size=%d", (char*) &type, size); 14482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden header.ts.type = type; 14502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden header.ts.size = (u4) size; 145164896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden if (sysWriteFully(fd, &header, sizeof(header), 1452e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein "DexOpt opt chunk header write") != 0) 145364896a2543ee54e47c586f4cf26f54e7fdb366bdAndy McFadden { 14542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 14552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (size > 0) { 1458e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein if (sysWriteFully(fd, data, size, "DexOpt opt chunk write") != 0) 14592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 14602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* if necessary, pad to 64-bit alignment */ 14632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if ((size & 7) != 0) { 14642e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden int padSize = 8 - (size & 7); 146592c1f6f1b4249e4e379452ee7b49f027052bf4ceSteve Block ALOGV("size was %d, inserting %d pad bytes", size, padSize); 14662e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden lseek(fd, padSize, SEEK_CUR); 14672e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14682e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14692e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden assert( ((int)lseek(fd, 0, SEEK_CUR) & 7) == 0); 14702e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14712e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return true; 14722e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 14732e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14742e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 1475e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * Write opt data. 14762e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 14772e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * We have different pieces, some of which may be optional. To make the 14782e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * most effective use of space, we use a "chunk" format, with a 4-byte 14792e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * type and a 4-byte length. We guarantee 64-bit alignment for the data, 14802e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * so it can be used directly when the file is mapped for reading. 14812e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 1482e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornsteinstatic bool writeOptData(int fd, const DexClassLookup* pClassLookup, 1483d394371bd84bacc51e96e2d2eacb8549d9110b1eDan Bornstein const RegisterMapBuilder* pRegMapBuilder) 14842e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 14852e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* pre-computed class lookup hash table */ 14862e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!writeChunk(fd, (u4) kDexChunkClassLookup, 14872e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pClassLookup, pClassLookup->size)) 14882e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 14892e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 14902e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14912e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 14922e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* register maps (optional) */ 14932e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (pRegMapBuilder != NULL) { 14942e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!writeChunk(fd, (u4) kDexChunkRegisterMaps, 14952e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pRegMapBuilder->data, pRegMapBuilder->size)) 14962e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden { 14972e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 14982e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 14992e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 15002e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15012e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* write the end marker */ 15022e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (!writeChunk(fd, (u4) kDexChunkEnd, NULL, 0)) { 15032e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 15042e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 15052e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15062e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return true; 15072e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 15082e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15092e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 15102e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Compute a checksum on a piece of an open file. 15112e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 15122e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * File will be positioned at end of checksummed area. 15132e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * 15142e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Returns "true" on success. 15152e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 15162e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic bool computeFileChecksum(int fd, off_t start, size_t length, u4* pSum) 15172e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 15182e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden unsigned char readBuf[8192]; 15192e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden ssize_t actual; 15202e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden uLong adler; 15212e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15222e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (lseek(fd, start, SEEK_SET) != start) { 1523c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Unable to seek to start of checksum area (%ld): %s", 15242e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (long) start, strerror(errno)); 15252e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 15262e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 15272e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15282e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden adler = adler32(0L, Z_NULL, 0); 15292e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15302e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden while (length != 0) { 15312e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden size_t wanted = (length < sizeof(readBuf)) ? length : sizeof(readBuf); 15322e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden actual = read(fd, readBuf, wanted); 15332e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden if (actual <= 0) { 1534c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block ALOGE("Read failed (%d) while computing checksum (len=%zu): %s", 15352e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden (int) actual, length, strerror(errno)); 15362e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return false; 15372e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 15382e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15392e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden adler = adler32(adler, readBuf, actual); 15402e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15412e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden length -= actual; 15422e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden } 15432e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15442e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden *pSum = adler; 15452e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden return true; 15462e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 15472e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15482e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden/* 15492e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Update the Adler-32 checksum stored in the DEX file. This covers the 15502e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * swapped and optimized DEX data, but does not include the opt header 1551e377ef62a40267ab16c2dd20cc5f4c63af6397ccDan Bornstein * or optimized data. 15522e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 15532e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFaddenstatic void updateChecksum(u1* addr, int len, DexHeader* pHeader) 15542e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden{ 15552e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden /* 15562e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden * Rewrite the checksum. We leave the SHA-1 signature alone. 15572e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden */ 15582e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden uLong adler = adler32(0L, Z_NULL, 0); 15592e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden const int nonSum = sizeof(pHeader->magic) + sizeof(pHeader->checksum); 15602e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden 15612e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden adler = adler32(adler, addr + nonSum, len - nonSum); 15622e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden pHeader->checksum = adler; 15632e1ee50a08cc3dd07ce4e956b925c1f0f28cf329Andy McFadden} 1564