OptMain.cpp revision 8911f7a2222124ba724a4a9281555b74d0e098e2
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 *
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There are two 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).
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * There are some fragile aspects around bootclasspath entries, owing
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * largely to the VM's history of working on whenever it thought it needed
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * instead of strictly doing what it was told.  If optimizing bootclasspath
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * entries, always do them in the order in which they appear in the path.
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "libdex/OptInvocation.h"
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
38f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "utils/Log.h"
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "cutils/process_name.h"
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdio.h>
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <string.h>
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic const char* kClassesDex = "classes.dex";
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Extract "classes.dex" from zipFd into "cacheFd", leaving a little space
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * up front for the DEX optimization header.
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int extractAndProcessZip(int zipFd, int cacheFd,
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* debugFileName, int isBootstrap, const char* bootClassPath,
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* dexoptFlagStr)
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ZipArchive zippy;
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ZipEntry zipEntry;
588911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden    size_t uncompLen;
598911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden    long modWhen, crc32;
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    off_t dexOffset;
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int err;
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = -1;
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    memset(&zippy, 0, sizeof(zippy));
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* make sure we're still at the start of an empty file */
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (lseek(cacheFd, 0, SEEK_END) != 0) {
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("DexOptZ: new cache file '%s' is not empty\n", debugFileName);
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Write a skeletal DEX optimization header.  We want the classes.dex
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to come just after it.
75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    err = dexOptCreateEmptyHeader(cacheFd);
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (err != 0)
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* record the file position so we can get back here later */
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexOffset = lseek(cacheFd, 0, SEEK_CUR);
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dexOffset < 0)
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Open the zip archive, find the DEX entry.
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dexZipPrepArchive(zipFd, debugFileName, &zippy) != 0) {
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("DexOptZ: unable to open zip archive '%s'\n", debugFileName);
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    zipEntry = dexZipFindEntry(&zippy, kClassesDex);
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (zipEntry == NULL) {
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("DexOptZ: zip archive '%s' does not include %s\n",
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            debugFileName, kClassesDex);
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Extract some info about the zip entry.
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1038911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden    if (dexZipGetEntryInfo(&zippy, zipEntry, NULL, &uncompLen, NULL, NULL,
1048911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden            &modWhen, &crc32) != 0)
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("DexOptZ: zip archive GetEntryInfo failed on %s\n", debugFileName);
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    uncompLen = uncompLen;
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    modWhen = modWhen;
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    crc32 = crc32;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Extract the DEX data into the cache file at the current offset.
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1178911f7a2222124ba724a4a9281555b74d0e098e2Andy McFadden    if (dexZipExtractEntryToFile(&zippy, zipEntry, cacheFd) != 0) {
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGW("DexOptZ: extraction of %s from %s failed\n",
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            kClassesDex, debugFileName);
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Prep the VM and perform the optimization.
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexClassVerifyMode verifyMode = VERIFY_MODE_ALL;
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOptimizerMode dexOptMode = OPTIMIZE_MODE_VERIFIED;
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int dexoptFlags = 0;        /* bit flags, from enum DexoptFlags */
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dexoptFlagStr[0] != '\0') {
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* opc;
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        const char* val;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        opc = strstr(dexoptFlagStr, "v=");      /* verification */
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (opc != NULL) {
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (*(opc+2)) {
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'n':   verifyMode = VERIFY_MODE_NONE;          break;
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'r':   verifyMode = VERIFY_MODE_REMOTE;        break;
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'a':   verifyMode = VERIFY_MODE_ALL;           break;
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:                                            break;
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        opc = strstr(dexoptFlagStr, "o=");      /* optimization */
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (opc != NULL) {
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            switch (*(opc+2)) {
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'n':   dexOptMode = OPTIMIZE_MODE_NONE;        break;
147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'v':   dexOptMode = OPTIMIZE_MODE_VERIFIED;    break;
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            case 'a':   dexOptMode = OPTIMIZE_MODE_ALL;         break;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            default:                                            break;
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        opc = strstr(dexoptFlagStr, "m=y");     /* register map */
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (opc != NULL) {
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexoptFlags |= DEXOPT_GEN_REGISTER_MAPS;
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmPrepForDexOpt(bootClassPath, dexOptMode, verifyMode,
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexoptFlags) != 0)
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("DexOptZ: VM init failed\n");
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //vmStarted = 1;
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* do the optimization */
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmContinueOptimization(cacheFd, dexOffset, uncompLen, debugFileName,
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            modWhen, crc32, isBootstrap))
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Optimization failed\n");
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* we don't shut the VM down -- process is about to exit */
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = 0;
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexZipCloseArchive(&zippy);
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* advance to the next arg and extract it */
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define GET_ARG(_var, _func, _msg)                                          \
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {                                                                       \
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* endp;                                                         \
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        (_var) = _func(*++argv, &endp, 0);                                  \
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*endp != '\0') {                                                \
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGE("%s '%s'", _msg, *argv);                                   \
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            goto bail;                                                      \
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }                                                                   \
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        --argc;                                                             \
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse arguments.  We want:
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   0. (name of dexopt command -- ignored)
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   1. "--zip"
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   2. zip fd (input, read-only)
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   3. cache fd (output, read-write, locked with flock)
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   4. filename of file being optimized (used for debug messages and
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      for comparing against BOOTCLASSPATH -- does not need to be
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      accessible or even exist)
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   5. dexopt flags
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The BOOTCLASSPATH environment variable is assumed to hold the correct
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * boot class path.  If the filename provided appears in the boot class
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * path, the path will be truncated just before that entry (so that, if
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you were to dexopt "core.jar", your bootclasspath would be empty).
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This does not try to normalize the boot class path name, so the
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * filename test won't catch you if you get creative.
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int fromZip(int argc, char* const argv[])
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = -1;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int zipFd, cacheFd, vmBuildVersion;
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* inputFileName;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* bcpCopy = NULL;
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* dexoptFlagStr;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (argc != 6) {
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Wrong number of args for --zip (found %d)\n", argc);
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* skip "--zip" */
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    argc--;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    argv++;
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_ARG(zipFd, strtol, "bad zip fd");
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_ARG(cacheFd, strtol, "bad cache fd");
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    inputFileName = *++argv;
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    --argc;
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dexoptFlagStr = *++argv;
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    --argc;
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Check to see if this is a bootstrap class entry.  If so, truncate
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the path.
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* bcp = getenv("BOOTCLASSPATH");
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (bcp == NULL) {
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("DexOptZ: BOOTCLASSPATH not set\n");
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int isBootstrap = false;
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* match = strstr(bcp, inputFileName);
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (match != NULL) {
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * TODO: we have a partial string match, but that doesn't mean
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * we've matched an entire path component.  We should make sure
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * that we're matching on the full inputFileName, and if not we
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * should re-do the strstr starting at (match+1).
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         *
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * The scenario would be a bootclasspath with something like
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "/system/framework/core.jar" while we're trying to optimize
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * "/framework/core.jar".  Not very likely since all paths are
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * absolute and end with ".jar", but not impossible.
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int matchOffset = match - bcp;
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (matchOffset > 0 && bcp[matchOffset-1] == ':')
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            matchOffset--;
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGV("DexOptZ: found '%s' in bootclasspath, cutting off at %d\n",
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            inputFileName, matchOffset);
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bcpCopy = strdup(bcp);
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bcpCopy[matchOffset] = '\0';
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bcp = bcpCopy;
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGD("DexOptZ: truncated BOOTCLASSPATH to '%s'\n", bcp);
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        isBootstrap = true;
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
277f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = extractAndProcessZip(zipFd, cacheFd, inputFileName,
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                isBootstrap, bcp, dexoptFlagStr);
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(bcpCopy);
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Parse arguments for an "old-style" invocation directly from the VM.
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Here's what we want:
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   0. (name of dexopt command -- ignored)
290f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   1. "--dex"
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   2. DALVIK_VM_BUILD value, as a sanity check
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   3. file descriptor, locked with flock, for DEX file being optimized
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   4. DEX offset within file
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   5. DEX length
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   6. filename of file being optimized (for debug messages only)
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   7. modification date of source (goes into dependency section)
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   8. CRC of source (goes into dependency section)
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   9. flags (optimization level, isBootstrap)
299f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  10. bootclasspath entry #1
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  11. bootclasspath entry #2
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *   ...
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dvmOptimizeDexFile() in dalvik/vm/analysis/DexOptimize.c builds the
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * argument list and calls this executable.
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The bootclasspath entries become the dependencies for this DEX file.
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The open file descriptor MUST NOT be for one of the bootclasspath files.
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The parent has the descriptor locked, and we'll try to lock it again as
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * part of processing the bootclasspath.  (We can catch this and return
311f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * an error by comparing filenames or by opening the bootclasspath files
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and stat()ing them for inode numbers).
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic int fromDex(int argc, char* const argv[])
315f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int result = -1;
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool vmStarted = false;
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* bootClassPath = NULL;
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int fd, flags, vmBuildVersion;
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    long offset, length;
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* debugFileName;
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    u4 crc, modWhen;
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* endp;
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (argc < 10) {
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* don't have all mandatory args */
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Not enough arguments for --dex (found %d)\n", argc);
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* skip "--dex" */
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    argc--;
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    argv++;
334f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Extract the args.
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_ARG(vmBuildVersion, strtol, "bad vm build");
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (vmBuildVersion != DALVIK_VM_BUILD) {
34087cf7312247b341b54be26904e3600e98967d695Andy McFadden        LOGE("DexOpt: build rev does not match VM: %d vs %d\n",
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            vmBuildVersion, DALVIK_VM_BUILD);
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_ARG(fd, strtol, "bad fd");
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_ARG(offset, strtol, "bad offset");
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_ARG(length, strtol, "bad length");
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    debugFileName = *++argv;
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    --argc;
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_ARG(modWhen, strtoul, "bad modWhen");
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_ARG(crc, strtoul, "bad crc");
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    GET_ARG(flags, strtol, "bad flags");
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
353f6c387128427e121477c1b32ad35cdcaa5101ba3The 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",
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fd, offset, length, debugFileName, modWhen, crc, flags, argc);
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(argc > 0);
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (--argc == 0) {
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bootClassPath = strdup("");
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int i, bcpLen;
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* const* argp;
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        char* cp;
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        bcpLen = 0;
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0, argp = argv; i < argc; i++) {
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ++argp;
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            LOGV("DEP: '%s'\n", *argp);
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bcpLen += strlen(*argp) + 1;
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        cp = bootClassPath = (char*) malloc(bcpLen +1);
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (i = 0, argp = argv; i < argc; i++) {
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int strLen;
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ++argp;
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            strLen = strlen(*argp);
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (i != 0)
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                *cp++ = ':';
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            memcpy(cp, *argp, strLen);
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            cp += strLen;
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        *cp = '\0';
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        assert((int) strlen(bootClassPath) == bcpLen-1);
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("  bootclasspath is '%s'\n", bootClassPath);
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* start the VM partway */
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    bool onlyOptVerifiedDex = false;
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexClassVerifyMode verifyMode;
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    DexOptimizerMode dexOptMode;
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int dexoptFlags = 0;
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* ugh -- upgrade these to a bit field if they get any more complex */
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((flags & DEXOPT_VERIFY_ENABLED) != 0) {
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((flags & DEXOPT_VERIFY_ALL) != 0)
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyMode = VERIFY_MODE_ALL;
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            verifyMode = VERIFY_MODE_REMOTE;
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        verifyMode = VERIFY_MODE_NONE;
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((flags & DEXOPT_OPT_ENABLED) != 0) {
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if ((flags & DEXOPT_OPT_ALL) != 0)
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexOptMode = OPTIMIZE_MODE_ALL;
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexOptMode = OPTIMIZE_MODE_VERIFIED;
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexOptMode = OPTIMIZE_MODE_NONE;
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if ((flags & DEXOPT_GEN_REGISTER_MAP) != 0) {
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dexoptFlags |= DEXOPT_GEN_REGISTER_MAPS;
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (dvmPrepForDexOpt(bootClassPath, dexOptMode, verifyMode,
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            dexoptFlags) != 0)
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("VM init failed\n");
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
420f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    vmStarted = true;
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* do the optimization */
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmContinueOptimization(fd, offset, length, debugFileName,
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            modWhen, crc, (flags & DEXOPT_IS_BOOTSTRAP) != 0))
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGE("Optimization failed\n");
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        goto bail;
430f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    result = 0;
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectbail:
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * In theory we should gracefully shut the VM down at this point.  In
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * practice that only matters if we're checking for memory leaks with
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * valgrind -- simply exiting is much faster.
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * As it turns out, the DEX optimizer plays a little fast and loose
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * with class loading.  We load all of the classes from a partially-
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * formed DEX file, which is unmapped when we're done.  If we want to
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * do clean shutdown here, perhaps for testing with valgrind, we need
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * to skip the munmap call there.
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (vmStarted) {
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("DexOpt shutting down, result=%d\n", result);
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        dvmShutdown();
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    //dvmLinearAllocDump(NULL);
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#if 0
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    {
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        extern int gDvm__totalInstr, gDvm__gcInstr, gDvm__gcData,
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project               gDvm__gcSimpleData;
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        LOGI("GC DATA: totinst=%d, gcinst=%d, gcdata=%d simpled=%d\n",
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            gDvm__totalInstr, gDvm__gcInstr, gDvm__gcData, gDvm__gcSimpleData);
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    free(bootClassPath);
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    LOGV("DexOpt command complete (result=%d)\n", result);
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return result;
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
469f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
470f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Main entry point.  Decide where to go.
471f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
472f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectint main(int argc, char* const argv[])
473f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
474f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    set_process_name("dexopt");
475f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
476f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    setvbuf(stdout, NULL, _IONBF, 0);
477f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
478f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (argc > 1) {
479f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (strcmp(argv[1], "--zip") == 0)
480f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return fromZip(argc, argv);
481f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        else if (strcmp(argv[1], "--dex") == 0)
482f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return fromDex(argc, argv);
483f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
484f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
485f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fprintf(stderr, "Usage: don't use this\n");
486f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return 1;
487f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
488f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
489