1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Command-line DEX optimization and verification entry point. 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 204701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * There are three ways to launch this: 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (1) From the VM. This takes a dozen args, one of which is a file 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptor that acts as both input and output. This allows us to 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * remain ignorant of where the DEX data originally came from. 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (2) From installd or another native application. Pass in a file 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * descriptor for a zip file, a file descriptor for the output, and 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * a filename for debug messages. Many assumptions are made about 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * what's going on (verification + optimization are enabled, boot 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * class path is in BOOTCLASSPATH, etc). 294701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * (3) On the host during a build for preoptimization. This behaves 304701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * almost the same as (2), except it takes file names instead of 314701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * file descriptors. 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There are some fragile aspects around bootclasspath entries, owing 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * largely to the VM's history of working on whenever it thought it needed 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instead of strictly doing what it was told. If optimizing bootclasspath 36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * entries, always do them in the order in which they appear in the path. 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h" 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/OptInvocation.h" 40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "utils/Log.h" 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "cutils/process_name.h" 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 444701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein#include <fcntl.h> 454701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein#include <stdbool.h> 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h> 47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h> 48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h> 49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kClassesDex = "classes.dex"; 51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Extract "classes.dex" from zipFd into "cacheFd", leaving a little space 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * up front for the DEX optimization header. 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int extractAndProcessZip(int zipFd, int cacheFd, 584701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein const char* debugFileName, bool isBootstrap, const char* bootClassPath, 59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* dexoptFlagStr) 60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ZipArchive zippy; 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ZipEntry zipEntry; 638911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden size_t uncompLen; 648911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden long modWhen, crc32; 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project off_t dexOffset; 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int err; 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = -1; 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memset(&zippy, 0, sizeof(zippy)); 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* make sure we're still at the start of an empty file */ 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (lseek(cacheFd, 0, SEEK_END) != 0) { 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("DexOptZ: new cache file '%s' is not empty\n", debugFileName); 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Write a skeletal DEX optimization header. We want the classes.dex 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to come just after it. 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project err = dexOptCreateEmptyHeader(cacheFd); 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (err != 0) 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* record the file position so we can get back here later */ 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexOffset = lseek(cacheFd, 0, SEEK_CUR); 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dexOffset < 0) 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Open the zip archive, find the DEX entry. 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dexZipPrepArchive(zipFd, debugFileName, &zippy) != 0) { 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("DexOptZ: unable to open zip archive '%s'\n", debugFileName); 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project zipEntry = dexZipFindEntry(&zippy, kClassesDex); 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (zipEntry == NULL) { 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("DexOptZ: zip archive '%s' does not include %s\n", 101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project debugFileName, kClassesDex); 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Extract some info about the zip entry. 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1088911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden if (dexZipGetEntryInfo(&zippy, zipEntry, NULL, &uncompLen, NULL, NULL, 1098911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden &modWhen, &crc32) != 0) 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("DexOptZ: zip archive GetEntryInfo failed on %s\n", debugFileName); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project uncompLen = uncompLen; 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project modWhen = modWhen; 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project crc32 = crc32; 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Extract the DEX data into the cache file at the current offset. 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 1228911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden if (dexZipExtractEntryToFile(&zippy, zipEntry, cacheFd) != 0) { 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGW("DexOptZ: extraction of %s from %s failed\n", 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project kClassesDex, debugFileName); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 128148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein /* Parse the options. */ 129148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexClassVerifyMode verifyMode = VERIFY_MODE_ALL; 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexOptimizerMode dexOptMode = OPTIMIZE_MODE_VERIFIED; 132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int dexoptFlags = 0; /* bit flags, from enum DexoptFlags */ 133148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dexoptFlagStr[0] != '\0') { 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* opc; 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* val; 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project opc = strstr(dexoptFlagStr, "v="); /* verification */ 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (opc != NULL) { 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (*(opc+2)) { 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'n': verifyMode = VERIFY_MODE_NONE; break; 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'r': verifyMode = VERIFY_MODE_REMOTE; break; 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'a': verifyMode = VERIFY_MODE_ALL; break; 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: break; 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project opc = strstr(dexoptFlagStr, "o="); /* optimization */ 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (opc != NULL) { 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project switch (*(opc+2)) { 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'n': dexOptMode = OPTIMIZE_MODE_NONE; break; 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'v': dexOptMode = OPTIMIZE_MODE_VERIFIED; break; 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project case 'a': dexOptMode = OPTIMIZE_MODE_ALL; break; 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project default: break; 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project opc = strstr(dexoptFlagStr, "m=y"); /* register map */ 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (opc != NULL) { 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexoptFlags |= DEXOPT_GEN_REGISTER_MAPS; 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 162148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein 163d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden opc = strstr(dexoptFlagStr, "u="); /* uniprocessor target */ 164148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein if (opc != NULL) { 165d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden switch (*(opc+2)) { 166d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden case 'y': dexoptFlags |= DEXOPT_UNIPROCESSOR; break; 167d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden case 'n': dexoptFlags |= DEXOPT_SMP; break; 168d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden default: break; 169d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden } 170148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein } 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 172148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein 173148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein /* 174148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein * Prep the VM and perform the optimization. 175148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein */ 176148283d71a7e35b9b506cbb49294b6822719c25eDan Bornstein 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (dvmPrepForDexOpt(bootClassPath, dexOptMode, verifyMode, 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexoptFlags) != 0) 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("DexOptZ: VM init failed\n"); 181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //vmStarted = 1; 185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* do the optimization */ 187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmContinueOptimization(cacheFd, dexOffset, uncompLen, debugFileName, 188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project modWhen, crc32, isBootstrap)) 189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Optimization failed\n"); 191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* we don't shut the VM down -- process is about to exit */ 195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = 0; 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexZipCloseArchive(&zippy); 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 2034701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein/* 2044701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * Common functionality for normal device-side processing as well as 2054701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * preoptimization. 2064701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein */ 2074701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornsteinstatic int processZipFile(int zipFd, int cacheFd, const char* zipName, 2084701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein const char *dexoptFlags) 2094701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein{ 2104701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein int result = -1; 2114701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein char* bcpCopy = NULL; 2124701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 2134701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein /* 2144701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * Check to see if this is a bootstrap class entry. If so, truncate 2154701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * the path. 2164701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein */ 2174701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein const char* bcp = getenv("BOOTCLASSPATH"); 2184701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein if (bcp == NULL) { 2194701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein LOGE("DexOptZ: BOOTCLASSPATH not set\n"); 2204701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein goto bail; 2214701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein } 2224701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 2234701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein bool isBootstrap = false; 2244701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein const char* match = strstr(bcp, zipName); 2254701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein if (match != NULL) { 2264701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein /* 2274701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * TODO: we have a partial string match, but that doesn't mean 2284701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * we've matched an entire path component. We should make sure 2294701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * that we're matching on the full zipName, and if not we 2304701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * should re-do the strstr starting at (match+1). 2314701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * 2324701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * The scenario would be a bootclasspath with something like 2334701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * "/system/framework/core.jar" while we're trying to optimize 2344701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * "/framework/core.jar". Not very likely since all paths are 2354701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * absolute and end with ".jar", but not impossible. 2364701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein */ 2374701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein int matchOffset = match - bcp; 2384701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein if (matchOffset > 0 && bcp[matchOffset-1] == ':') 2394701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein matchOffset--; 2404701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein LOGV("DexOptZ: found '%s' in bootclasspath, cutting off at %d\n", 2414701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein inputFileName, matchOffset); 2424701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein bcpCopy = strdup(bcp); 2434701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein bcpCopy[matchOffset] = '\0'; 2444701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 2454701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein bcp = bcpCopy; 2464701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein LOGD("DexOptZ: truncated BOOTCLASSPATH to '%s'\n", bcp); 2474701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein isBootstrap = true; 2484701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein } 2494701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 2504701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein result = extractAndProcessZip(zipFd, cacheFd, zipName, isBootstrap, 2514701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein bcp, dexoptFlags); 2524701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 2534701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornsteinbail: 2544701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein free(bcpCopy); 2554701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein return result; 2564701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein} 257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* advance to the next arg and extract it */ 259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define GET_ARG(_var, _func, _msg) \ 260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { \ 261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* endp; \ 262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project (_var) = _func(*++argv, &endp, 0); \ 263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (*endp != '\0') { \ 264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("%s '%s'", _msg, *argv); \ 265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; \ 266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } \ 267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project --argc; \ 268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse arguments. We want: 272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 0. (name of dexopt command -- ignored) 273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1. "--zip" 274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 2. zip fd (input, read-only) 275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 3. cache fd (output, read-write, locked with flock) 2764701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * 4. filename of zipfile being optimized (used for debug messages and 2774701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * for comparing against BOOTCLASSPATH; does not need to be 278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * accessible or even exist) 279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 5. dexopt flags 280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The BOOTCLASSPATH environment variable is assumed to hold the correct 282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * boot class path. If the filename provided appears in the boot class 283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * path, the path will be truncated just before that entry (so that, if 284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you were to dexopt "core.jar", your bootclasspath would be empty). 285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not try to normalize the boot class path name, so the 287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * filename test won't catch you if you get creative. 288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int fromZip(int argc, char* const argv[]) 290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = -1; 2924701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein int zipFd, cacheFd; 2934701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein const char* zipName; 294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* bcpCopy = NULL; 2954701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein const char* dexoptFlags; 296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argc != 6) { 298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Wrong number of args for --zip (found %d)\n", argc); 299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* skip "--zip" */ 303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argc--; 304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argv++; 305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GET_ARG(zipFd, strtol, "bad zip fd"); 307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GET_ARG(cacheFd, strtol, "bad cache fd"); 3084701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein zipName = *++argv; 309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project --argc; 3104701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein dexoptFlags = *++argv; 311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project --argc; 312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3134701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein result = processZipFile(zipFd, cacheFd, zipName, dexoptFlags); 3144701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 3154701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornsteinbail: 3164701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein return result; 3174701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein} 3184701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 3194701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein/* 3204701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * Parse arguments for a preoptimization run. This is when dalvikvm is run 3214701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * on a host to optimize dex files for eventual running on a (different) 3224701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * device. We want: 3234701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * 0. (name of dexopt command -- ignored) 3244701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * 1. "--preopt" 3254701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * 2. zipfile name 3264701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * 3. output file name 3274701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * 4. dexopt flags 3284701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * 3294701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * The BOOTCLASSPATH environment variable is assumed to hold the correct 3304701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * boot class path. If the filename provided appears in the boot class 3314701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * path, the path will be truncated just before that entry (so that, if 3324701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * you were to dexopt "core.jar", your bootclasspath would be empty). 3334701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * 3344701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * This does not try to normalize the boot class path name, so the 3354701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein * filename test won't catch you if you get creative. 3364701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein */ 3374701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornsteinstatic int preopt(int argc, char* const argv[]) 3384701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein{ 339dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein int zipFd = -1; 340dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein int outFd = -1; 341dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein int result = -1; 342dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein 3434701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein if (argc != 5) { 344dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein /* 345dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein * Use stderr here, since this variant is meant to be called on 346dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein * the host side. 347dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein */ 348dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein fprintf(stderr, "Wrong number of args for --preopt (found %d)\n", 349dd2502bd371ddca554b7a3d900fe120a3e7767ecDan Bornstein argc); 350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3534701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein const char* zipName = argv[2]; 3544701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein const char* outName = argv[3]; 3554701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein const char* dexoptFlags = argv[4]; 356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 357d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden if (strstr(dexoptFlags, "u=y") == NULL && 358d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden strstr(dexoptFlags, "u=n") == NULL) 359d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden { 360d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden fprintf(stderr, "Either 'u=y' or 'u=n' must be specified\n"); 361d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden goto bail; 362d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden } 363d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden 3644701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein zipFd = open(zipName, O_RDONLY); 3654701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein if (zipFd < 0) { 3664701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein perror(argv[0]); 3674701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein goto bail; 3684701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein } 3694701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 37046f7d54cbda931213bbe710c065e1bd82aa0af6cDan Bornstein outFd = open(outName, O_RDWR | O_EXCL | O_CREAT, 0666); 3714701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein if (outFd < 0) { 3724701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein perror(argv[0]); 3734701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein goto bail; 374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3764701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein result = processZipFile(zipFd, outFd, zipName, dexoptFlags); 377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 3794701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein if (zipFd >= 0) { 3804701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein close(zipFd); 3814701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein } 3824701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 3834701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein if (outFd >= 0) { 3844701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein close(outFd); 3854701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein } 3864701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse arguments for an "old-style" invocation directly from the VM. 392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Here's what we want: 394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 0. (name of dexopt command -- ignored) 395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 1. "--dex" 396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 2. DALVIK_VM_BUILD value, as a sanity check 397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 3. file descriptor, locked with flock, for DEX file being optimized 398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4. DEX offset within file 399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 5. DEX length 400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 6. filename of file being optimized (for debug messages only) 401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 7. modification date of source (goes into dependency section) 402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8. CRC of source (goes into dependency section) 403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 9. flags (optimization level, isBootstrap) 404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10. bootclasspath entry #1 405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 11. bootclasspath entry #2 406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * ... 407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmOptimizeDexFile() in dalvik/vm/analysis/DexOptimize.c builds the 409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * argument list and calls this executable. 410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The bootclasspath entries become the dependencies for this DEX file. 412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The open file descriptor MUST NOT be for one of the bootclasspath files. 414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The parent has the descriptor locked, and we'll try to lock it again as 415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * part of processing the bootclasspath. (We can catch this and return 416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an error by comparing filenames or by opening the bootclasspath files 417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and stat()ing them for inode numbers). 418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int fromDex(int argc, char* const argv[]) 420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int result = -1; 422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool vmStarted = false; 423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* bootClassPath = NULL; 424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int fd, flags, vmBuildVersion; 425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project long offset, length; 426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project const char* debugFileName; 427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project u4 crc, modWhen; 428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* endp; 429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argc < 10) { 431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* don't have all mandatory args */ 432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Not enough arguments for --dex (found %d)\n", argc); 433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* skip "--dex" */ 437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argc--; 438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project argv++; 439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Extract the args. 442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GET_ARG(vmBuildVersion, strtol, "bad vm build"); 444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (vmBuildVersion != DALVIK_VM_BUILD) { 44587cf7312247b341b54be26904e3600e98967d695Andy McFadden LOGE("DexOpt: build rev does not match VM: %d vs %d\n", 446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vmBuildVersion, DALVIK_VM_BUILD); 447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GET_ARG(fd, strtol, "bad fd"); 450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GET_ARG(offset, strtol, "bad offset"); 451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GET_ARG(length, strtol, "bad length"); 452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project debugFileName = *++argv; 453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project --argc; 454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GET_ARG(modWhen, strtoul, "bad modWhen"); 455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GET_ARG(crc, strtoul, "bad crc"); 456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project GET_ARG(flags, strtol, "bad flags"); 457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("Args: fd=%d off=%ld len=%ld name='%s' mod=0x%x crc=0x%x flg=%d (argc=%d)\n", 459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project fd, offset, length, debugFileName, modWhen, crc, flags, argc); 460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert(argc > 0); 461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (--argc == 0) { 463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bootClassPath = strdup(""); 464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int i, bcpLen; 466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* const* argp; 467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project char* cp; 468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bcpLen = 0; 470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0, argp = argv; i < argc; i++) { 471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ++argp; 472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("DEP: '%s'\n", *argp); 473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bcpLen += strlen(*argp) + 1; 474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cp = bootClassPath = (char*) malloc(bcpLen +1); 477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (i = 0, argp = argv; i < argc; i++) { 478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int strLen; 479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project ++argp; 481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project strLen = strlen(*argp); 482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (i != 0) 483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp++ = ':'; 484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project memcpy(cp, *argp, strLen); 485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project cp += strLen; 486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *cp = '\0'; 488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 489f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project assert((int) strlen(bootClassPath) == bcpLen-1); 490f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 491f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV(" bootclasspath is '%s'\n", bootClassPath); 492f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 493f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* start the VM partway */ 494f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project bool onlyOptVerifiedDex = false; 495f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexClassVerifyMode verifyMode; 496f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DexOptimizerMode dexOptMode; 497f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 498f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* ugh -- upgrade these to a bit field if they get any more complex */ 499f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((flags & DEXOPT_VERIFY_ENABLED) != 0) { 500f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((flags & DEXOPT_VERIFY_ALL) != 0) 501f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyMode = VERIFY_MODE_ALL; 502f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 503f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyMode = VERIFY_MODE_REMOTE; 504f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 505f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project verifyMode = VERIFY_MODE_NONE; 506f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 507f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((flags & DEXOPT_OPT_ENABLED) != 0) { 508f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if ((flags & DEXOPT_OPT_ALL) != 0) 509f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexOptMode = OPTIMIZE_MODE_ALL; 510f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else 511f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexOptMode = OPTIMIZE_MODE_VERIFIED; 512f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } else { 513f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dexOptMode = OPTIMIZE_MODE_NONE; 514f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 515f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 516d8b5f50d0c6c9a0ce157e89df4ee1e8eb8b334c3Andy McFadden if (dvmPrepForDexOpt(bootClassPath, dexOptMode, verifyMode, flags) != 0) { 517f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("VM init failed\n"); 518f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 519f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 520f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 521f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project vmStarted = true; 522f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 523f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* do the optimization */ 524f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (!dvmContinueOptimization(fd, offset, length, debugFileName, 525f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project modWhen, crc, (flags & DEXOPT_IS_BOOTSTRAP) != 0)) 526f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 527f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGE("Optimization failed\n"); 528f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project goto bail; 529f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 530f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 531f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project result = 0; 532f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 533f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail: 534f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /* 535f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * In theory we should gracefully shut the VM down at this point. In 536f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * practice that only matters if we're checking for memory leaks with 537f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * valgrind -- simply exiting is much faster. 538f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 539f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * As it turns out, the DEX optimizer plays a little fast and loose 540f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * with class loading. We load all of the classes from a partially- 541f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * formed DEX file, which is unmapped when we're done. If we want to 542f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * do clean shutdown here, perhaps for testing with valgrind, we need 543f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to skip the munmap call there. 544f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 545f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 546f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (vmStarted) { 547f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("DexOpt shutting down, result=%d\n", result); 548f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project dvmShutdown(); 549f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 550f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 551f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 552f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project //dvmLinearAllocDump(NULL); 553f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 554f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0 555f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project { 556f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project extern int gDvm__totalInstr, gDvm__gcInstr, gDvm__gcData, 557f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm__gcSimpleData; 558f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGI("GC DATA: totinst=%d, gcinst=%d, gcdata=%d simpled=%d\n", 559f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project gDvm__totalInstr, gDvm__gcInstr, gDvm__gcData, gDvm__gcSimpleData); 560f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 561f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif 562f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 563f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project free(bootClassPath); 564f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project LOGV("DexOpt command complete (result=%d)\n", result); 565f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return result; 566f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 567f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 568f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 569f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Main entry point. Decide where to go. 570f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 571f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint main(int argc, char* const argv[]) 572f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{ 573f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project set_process_name("dexopt"); 574f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 575f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project setvbuf(stdout, NULL, _IONBF, 0); 576f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 577f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (argc > 1) { 578f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (strcmp(argv[1], "--zip") == 0) 579f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return fromZip(argc, argv); 580f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project else if (strcmp(argv[1], "--dex") == 0) 581f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return fromDex(argc, argv); 5824701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein else if (strcmp(argv[1], "--preopt") == 0) 5834701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein return preopt(argc, argv); 584f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 585f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 5864701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein fprintf(stderr, 5874701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein "Usage:\n\n" 5884701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein "Short version: Don't use this.\n\n" 5894701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein "Slightly longer version: This system-internal tool is used to\n" 5904701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein "produce optimized dex files. See the source code for details.\n"); 5914701d5f8d0e691eeb9a0824311d5166d301a5aa5Dan Bornstein 592f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return 1; 593f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 594