/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Command-line DEX optimization and verification entry point.
 *
 * There are two ways to launch this:
 * (1) From the VM.  This takes a dozen args, one of which is a file
 *     descriptor that acts as both input and output.  This allows us to
 *     remain ignorant of where the DEX data originally came from.
 * (2) From installd or another native application.  Pass in a file
 *     descriptor for a zip file, a file descriptor for the output, and
 *     a filename for debug messages.  Many assumptions are made about
 *     what's going on (verification + optimization are enabled, boot
 *     class path is in BOOTCLASSPATH, etc).
 *
 * There are some fragile aspects around bootclasspath entries, owing
 * largely to the VM's history of working on whenever it thought it needed
 * instead of strictly doing what it was told.  If optimizing bootclasspath
 * entries, always do them in the order in which they appear in the path.
 */
#include "Dalvik.h"
#include "libdex/OptInvocation.h"

#include "utils/Log.h"
#include "cutils/process_name.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

static const char* kClassesDex = "classes.dex";


/*
 * Extract "classes.dex" from zipFd into "cacheFd", leaving a little space
 * up front for the DEX optimization header.
 */
static int extractAndProcessZip(int zipFd, int cacheFd,
    const char* debugFileName, int isBootstrap, const char* bootClassPath,
    const char* dexoptFlagStr)
{
    ZipArchive zippy;
    ZipEntry zipEntry;
    long uncompLen, modWhen, crc32;
    off_t dexOffset;
    int err;
    int result = -1;

    memset(&zippy, 0, sizeof(zippy));

    /* make sure we're still at the start of an empty file */
    if (lseek(cacheFd, 0, SEEK_END) != 0) {
        LOGE("DexOptZ: new cache file '%s' is not empty\n", debugFileName);
        goto bail;
    }

    /*
     * Write a skeletal DEX optimization header.  We want the classes.dex
     * to come just after it.
     */
    err = dexOptCreateEmptyHeader(cacheFd);
    if (err != 0)
        goto bail;

    /* record the file position so we can get back here later */
    dexOffset = lseek(cacheFd, 0, SEEK_CUR);
    if (dexOffset < 0)
        goto bail;

    /*
     * Open the zip archive, find the DEX entry.
     */
    if (dexZipPrepArchive(zipFd, debugFileName, &zippy) != 0) {
        LOGW("DexOptZ: unable to open zip archive '%s'\n", debugFileName);
        goto bail;
    }

    zipEntry = dexZipFindEntry(&zippy, kClassesDex);
    if (zipEntry == NULL) {
        LOGW("DexOptZ: zip archive '%s' does not include %s\n",
            debugFileName, kClassesDex);
        goto bail;
    }

    /*
     * Extract some info about the zip entry.
     */
    if (!dexZipGetEntryInfo(&zippy, zipEntry, NULL, &uncompLen, NULL, NULL,
            &modWhen, &crc32))
    {
        LOGW("DexOptZ: zip archive GetEntryInfo failed on %s\n", debugFileName);
        goto bail;
    }

    uncompLen = uncompLen;
    modWhen = modWhen;
    crc32 = crc32;

    /*
     * Extract the DEX data into the cache file at the current offset.
     */
    if (!dexZipExtractEntryToFile(&zippy, zipEntry, cacheFd)) {
        LOGW("DexOptZ: extraction of %s from %s failed\n",
            kClassesDex, debugFileName);
        goto bail;
    }

    /*
     * Prep the VM and perform the optimization.
     */
    DexClassVerifyMode verifyMode = VERIFY_MODE_ALL;
    DexOptimizerMode dexOptMode = OPTIMIZE_MODE_VERIFIED;
    int dexoptFlags = 0;        /* bit flags, from enum DexoptFlags */
    if (dexoptFlagStr[0] != '\0') {
        const char* opc;
        const char* val;

        opc = strstr(dexoptFlagStr, "v=");      /* verification */
        if (opc != NULL) {
            switch (*(opc+2)) {
            case 'n':   verifyMode = VERIFY_MODE_NONE;          break;
            case 'r':   verifyMode = VERIFY_MODE_REMOTE;        break;
            case 'a':   verifyMode = VERIFY_MODE_ALL;           break;
            default:                                            break;
            }
        }

        opc = strstr(dexoptFlagStr, "o=");      /* optimization */
        if (opc != NULL) {
            switch (*(opc+2)) {
            case 'n':   dexOptMode = OPTIMIZE_MODE_NONE;        break;
            case 'v':   dexOptMode = OPTIMIZE_MODE_VERIFIED;    break;
            case 'a':   dexOptMode = OPTIMIZE_MODE_ALL;         break;
            default:                                            break;
            }
        }

        opc = strstr(dexoptFlagStr, "m=y");     /* register map */
        if (opc != NULL) {
            dexoptFlags |= DEXOPT_GEN_REGISTER_MAPS;
        }
    }
    if (dvmPrepForDexOpt(bootClassPath, dexOptMode, verifyMode,
            dexoptFlags) != 0)
    {
        LOGE("DexOptZ: VM init failed\n");
        goto bail;
    }

    //vmStarted = 1;

    /* do the optimization */
    if (!dvmContinueOptimization(cacheFd, dexOffset, uncompLen, debugFileName,
            modWhen, crc32, isBootstrap))
    {
        LOGE("Optimization failed\n");
        goto bail;
    }

    /* we don't shut the VM down -- process is about to exit */

    result = 0;

bail:
    dexZipCloseArchive(&zippy);
    return result;
}


/* advance to the next arg and extract it */
#define GET_ARG(_var, _func, _msg)                                          \
    {                                                                       \
        char* endp;                                                         \
        (_var) = _func(*++argv, &endp, 0);                                  \
        if (*endp != '\0') {                                                \
            LOGE("%s '%s'", _msg, *argv);                                   \
            goto bail;                                                      \
        }                                                                   \
        --argc;                                                             \
    }

/*
 * Parse arguments.  We want:
 *   0. (name of dexopt command -- ignored)
 *   1. "--zip"
 *   2. zip fd (input, read-only)
 *   3. cache fd (output, read-write, locked with flock)
 *   4. filename of file being optimized (used for debug messages and
 *      for comparing against BOOTCLASSPATH -- does not need to be
 *      accessible or even exist)
 *   5. dexopt flags
 *
 * The BOOTCLASSPATH environment variable is assumed to hold the correct
 * boot class path.  If the filename provided appears in the boot class
 * path, the path will be truncated just before that entry (so that, if
 * you were to dexopt "core.jar", your bootclasspath would be empty).
 *
 * This does not try to normalize the boot class path name, so the
 * filename test won't catch you if you get creative.
 */
static int fromZip(int argc, char* const argv[])
{
    int result = -1;
    int zipFd, cacheFd, vmBuildVersion;
    const char* inputFileName;
    char* bcpCopy = NULL;
    const char* dexoptFlagStr;

    if (argc != 6) {
        LOGE("Wrong number of args for --zip (found %d)\n", argc);
        goto bail;
    }

    /* skip "--zip" */
    argc--;
    argv++;

    GET_ARG(zipFd, strtol, "bad zip fd");
    GET_ARG(cacheFd, strtol, "bad cache fd");
    inputFileName = *++argv;
    --argc;
    dexoptFlagStr = *++argv;
    --argc;

    /*
     * Check to see if this is a bootstrap class entry.  If so, truncate
     * the path.
     */
    const char* bcp = getenv("BOOTCLASSPATH");
    if (bcp == NULL) {
        LOGE("DexOptZ: BOOTCLASSPATH not set\n");
        goto bail;
    }

    int isBootstrap = false;
    const char* match = strstr(bcp, inputFileName);
    if (match != NULL) {
        /*
         * TODO: we have a partial string match, but that doesn't mean
         * we've matched an entire path component.  We should make sure
         * that we're matching on the full inputFileName, and if not we
         * should re-do the strstr starting at (match+1).
         *
         * The scenario would be a bootclasspath with something like
         * "/system/framework/core.jar" while we're trying to optimize
         * "/framework/core.jar".  Not very likely since all paths are
         * absolute and end with ".jar", but not impossible.
         */
        int matchOffset = match - bcp;
        if (matchOffset > 0 && bcp[matchOffset-1] == ':')
            matchOffset--;
        LOGV("DexOptZ: found '%s' in bootclasspath, cutting off at %d\n",
            inputFileName, matchOffset);
        bcpCopy = strdup(bcp);
        bcpCopy[matchOffset] = '\0';

        bcp = bcpCopy;
        LOGD("DexOptZ: truncated BOOTCLASSPATH to '%s'\n", bcp);
        isBootstrap = true;
    }

    result = extractAndProcessZip(zipFd, cacheFd, inputFileName,
                isBootstrap, bcp, dexoptFlagStr);

bail:
    free(bcpCopy);
    return result;
}

/*
 * Parse arguments for an "old-style" invocation directly from the VM.
 *
 * Here's what we want:
 *   0. (name of dexopt command -- ignored)
 *   1. "--dex"
 *   2. DALVIK_VM_BUILD value, as a sanity check
 *   3. file descriptor, locked with flock, for DEX file being optimized
 *   4. DEX offset within file
 *   5. DEX length
 *   6. filename of file being optimized (for debug messages only)
 *   7. modification date of source (goes into dependency section)
 *   8. CRC of source (goes into dependency section)
 *   9. flags (optimization level, isBootstrap)
 *  10. bootclasspath entry #1
 *  11. bootclasspath entry #2
 *   ...
 *
 * dvmOptimizeDexFile() in dalvik/vm/analysis/DexOptimize.c builds the
 * argument list and calls this executable.
 *
 * The bootclasspath entries become the dependencies for this DEX file.
 *
 * The open file descriptor MUST NOT be for one of the bootclasspath files.
 * The parent has the descriptor locked, and we'll try to lock it again as
 * part of processing the bootclasspath.  (We can catch this and return
 * an error by comparing filenames or by opening the bootclasspath files
 * and stat()ing them for inode numbers).
 */
static int fromDex(int argc, char* const argv[])
{
    int result = -1;
    bool vmStarted = false;
    char* bootClassPath = NULL;
    int fd, flags, vmBuildVersion;
    long offset, length;
    const char* debugFileName;
    u4 crc, modWhen;
    char* endp;

    if (argc < 10) {
        /* don't have all mandatory args */
        LOGE("Not enough arguments for --dex (found %d)\n", argc);
        goto bail;
    }

    /* skip "--dex" */
    argc--;
    argv++;

    /*
     * Extract the args.
     */
    GET_ARG(vmBuildVersion, strtol, "bad vm build");
    if (vmBuildVersion != DALVIK_VM_BUILD) {
        LOGE("DexOpt: build rev does not match VM: %d vs %d\n",
            vmBuildVersion, DALVIK_VM_BUILD);
        goto bail;
    }
    GET_ARG(fd, strtol, "bad fd");
    GET_ARG(offset, strtol, "bad offset");
    GET_ARG(length, strtol, "bad length");
    debugFileName = *++argv;
    --argc;
    GET_ARG(modWhen, strtoul, "bad modWhen");
    GET_ARG(crc, strtoul, "bad crc");
    GET_ARG(flags, strtol, "bad flags");

    LOGV("Args: fd=%d off=%ld len=%ld name='%s' mod=0x%x crc=0x%x flg=%d (argc=%d)\n",
        fd, offset, length, debugFileName, modWhen, crc, flags, argc);
    assert(argc > 0);

    if (--argc == 0) {
        bootClassPath = strdup("");
    } else {
        int i, bcpLen;
        char* const* argp;
        char* cp;

        bcpLen = 0;
        for (i = 0, argp = argv; i < argc; i++) {
            ++argp;
            LOGV("DEP: '%s'\n", *argp);
            bcpLen += strlen(*argp) + 1;
        }

        cp = bootClassPath = (char*) malloc(bcpLen +1);
        for (i = 0, argp = argv; i < argc; i++) {
            int strLen;

            ++argp;
            strLen = strlen(*argp);
            if (i != 0)
                *cp++ = ':';
            memcpy(cp, *argp, strLen);
            cp += strLen;
        }
        *cp = '\0';

        assert((int) strlen(bootClassPath) == bcpLen-1);
    }
    LOGV("  bootclasspath is '%s'\n", bootClassPath);

    /* start the VM partway */
    bool onlyOptVerifiedDex = false;
    DexClassVerifyMode verifyMode;
    DexOptimizerMode dexOptMode;
    int dexoptFlags = 0;

    /* ugh -- upgrade these to a bit field if they get any more complex */
    if ((flags & DEXOPT_VERIFY_ENABLED) != 0) {
        if ((flags & DEXOPT_VERIFY_ALL) != 0)
            verifyMode = VERIFY_MODE_ALL;
        else
            verifyMode = VERIFY_MODE_REMOTE;
    } else {
        verifyMode = VERIFY_MODE_NONE;
    }
    if ((flags & DEXOPT_OPT_ENABLED) != 0) {
        if ((flags & DEXOPT_OPT_ALL) != 0)
            dexOptMode = OPTIMIZE_MODE_ALL;
        else
            dexOptMode = OPTIMIZE_MODE_VERIFIED;
    } else {
        dexOptMode = OPTIMIZE_MODE_NONE;
    }
    if ((flags & DEXOPT_GEN_REGISTER_MAP) != 0) {
        dexoptFlags |= DEXOPT_GEN_REGISTER_MAPS;
    }

    if (dvmPrepForDexOpt(bootClassPath, dexOptMode, verifyMode,
            dexoptFlags) != 0)
    {
        LOGE("VM init failed\n");
        goto bail;
    }

    vmStarted = true;

    /* do the optimization */
    if (!dvmContinueOptimization(fd, offset, length, debugFileName,
            modWhen, crc, (flags & DEXOPT_IS_BOOTSTRAP) != 0))
    {
        LOGE("Optimization failed\n");
        goto bail;
    }

    result = 0;

bail:
    /*
     * In theory we should gracefully shut the VM down at this point.  In
     * practice that only matters if we're checking for memory leaks with
     * valgrind -- simply exiting is much faster.
     *
     * As it turns out, the DEX optimizer plays a little fast and loose
     * with class loading.  We load all of the classes from a partially-
     * formed DEX file, which is unmapped when we're done.  If we want to
     * do clean shutdown here, perhaps for testing with valgrind, we need
     * to skip the munmap call there.
     */
#if 0
    if (vmStarted) {
        LOGI("DexOpt shutting down, result=%d\n", result);
        dvmShutdown();
    }
#endif

    //dvmLinearAllocDump(NULL);

#if 0
    {
        extern int gDvm__totalInstr, gDvm__gcInstr, gDvm__gcData,
               gDvm__gcSimpleData;
        LOGI("GC DATA: totinst=%d, gcinst=%d, gcdata=%d simpled=%d\n",
            gDvm__totalInstr, gDvm__gcInstr, gDvm__gcData, gDvm__gcSimpleData);
    }
#endif

    free(bootClassPath);
    LOGV("DexOpt command complete (result=%d)\n", result);
    return result;
}

/*
 * Main entry point.  Decide where to go.
 */
int main(int argc, char* const argv[])
{
    set_process_name("dexopt");

    setvbuf(stdout, NULL, _IONBF, 0);

    if (argc > 1) {
        if (strcmp(argv[1], "--zip") == 0)
            return fromZip(argc, argv);
        else if (strcmp(argv[1], "--dex") == 0)
            return fromDex(argc, argv);
    }

    fprintf(stderr, "Usage: don't use this\n");
    return 1;
}

