/*
 * 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.
 */

/*
 * List all methods in all concrete classes in one or more DEX files.
 */

#include "libdex/DexFile.h"

#include "libdex/CmdUtils.h"
#include "libdex/DexClass.h"
#include "libdex/DexDebugInfo.h"
#include "libdex/DexProto.h"
#include "libdex/SysUtil.h"

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <stddef.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <assert.h>

static const char* gProgName = "dexlist";

/* command-line args */
static struct {
    char*       argCopy;
    const char* classToFind;
    const char* methodToFind;
} gParms;


/*
 * Return a newly-allocated string for the "dot version" of the class
 * name for the given type descriptor. That is, The initial "L" and
 * final ";" (if any) have been removed and all occurrences of '/'
 * have been changed to '.'.
 */
static char* descriptorToDot(const char* str)
{
    size_t at = strlen(str);
    char* newStr;

    if (str[0] == 'L') {
        assert(str[at - 1] == ';');
        at -= 2; /* Two fewer chars to copy. */
        str++; /* Skip the 'L'. */
    }

    newStr = malloc(at + 1); /* Add one for the '\0'. */
    newStr[at] = '\0';

    while (at > 0) {
        at--;
        newStr[at] = (str[at] == '/') ? '.' : str[at];
    }

    return newStr;
}

/*
 * Position table callback; we just want to catch the number of the
 * first line in the method, which *should* correspond to the first
 * entry from the table.  (Could also use "min" here.)
 */
static int positionsCallback(void* cnxt, u4 address, u4 lineNum)
{
    int* pFirstLine = (int*) cnxt;
    if (*pFirstLine == -1)
        *pFirstLine = lineNum;
    return 0;
}


/*
 * Dump a method.
 */
void dumpMethod(DexFile* pDexFile, const char* fileName,
    const DexMethod* pDexMethod, int i)
{
    const DexMethodId* pMethodId;
    const DexCode* pCode;
    const char* classDescriptor;
    const char* methodName;
    int firstLine;

    /* abstract and native methods don't get listed */
    if (pDexMethod->codeOff == 0)
        return;

    pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
    methodName = dexStringById(pDexFile, pMethodId->nameIdx);

    classDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);

    pCode = dexGetCode(pDexFile, pDexMethod);
    assert(pCode != NULL);

    /*
     * If the filename is empty, then set it to something printable
     * so that it is easier to parse.
     *
     * TODO: A method may override its class's default source file by
     * specifying a different one in its debug info. This possibility
     * should be handled here.
     */
    if (fileName == NULL || fileName[0] == 0) {
        fileName = "(none)";
    }

    firstLine = -1;
    dexDecodeDebugInfo(pDexFile, pCode, classDescriptor, pMethodId->protoIdx,
        pDexMethod->accessFlags, positionsCallback, NULL, &firstLine);

    char* className = descriptorToDot(classDescriptor);
    char* desc = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
    u4 insnsOff = pDexMethod->codeOff + offsetof(DexCode, insns);

    if (gParms.methodToFind != NULL &&
        (strcmp(gParms.classToFind, className) != 0 ||
         strcmp(gParms.methodToFind, methodName) != 0))
    {
        goto skip;
    }

    printf("0x%08x %d %s %s %s %s %d\n",
        insnsOff, pCode->insnsSize * 2,
        className, methodName, desc,
        fileName, firstLine);

skip:
    free(desc);
    free(className);
}

/*
 * Run through all direct and virtual methods in the class.
 */
void dumpClass(DexFile* pDexFile, int idx)
{
    const DexClassDef* pClassDef;
    DexClassData* pClassData;
    const u1* pEncodedData;
    const char* fileName;
    int i;

    pClassDef = dexGetClassDef(pDexFile, idx);
    pEncodedData = dexGetClassData(pDexFile, pClassDef);
    pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);

    if (pClassData == NULL) {
        fprintf(stderr, "Trouble reading class data\n");
        return;
    }

    if (pClassDef->sourceFileIdx == 0xffffffff) {
        fileName = NULL;
    } else {
        fileName = dexStringById(pDexFile, pClassDef->sourceFileIdx);
    }

    /*
     * TODO: Each class def points at a sourceFile, so maybe that
     * should be printed out. However, this needs to be coordinated
     * with the tools that parse this output.
     */

    for (i = 0; i < (int) pClassData->header.directMethodsSize; i++) {
        dumpMethod(pDexFile, fileName, &pClassData->directMethods[i], i);
    }

    for (i = 0; i < (int) pClassData->header.virtualMethodsSize; i++) {
        dumpMethod(pDexFile, fileName, &pClassData->virtualMethods[i], i);
    }

    free(pClassData);
}

/*
 * Process a file.
 *
 * Returns 0 on success.
 */
int process(const char* fileName)
{
    DexFile* pDexFile = NULL;
    MemMapping map;
    bool mapped = false;
    int result = -1;
    UnzipToFileResult utfr;

    utfr = dexOpenAndMap(fileName, NULL, &map, true);
    if (utfr != kUTFRSuccess) {
        if (utfr == kUTFRNoClassesDex) {
            /* no classes.dex in the APK; pretend we succeeded */
            result = 0;
            goto bail;
        }
        fprintf(stderr, "Unable to process '%s'\n", fileName);
        goto bail;
    }
    mapped = true;

    pDexFile = dexFileParse(map.addr, map.length, kDexParseDefault);
    if (pDexFile == NULL) {
        fprintf(stderr, "Warning: DEX parse failed for '%s'\n", fileName);
        goto bail;
    }

    printf("#%s\n", fileName);

    int i;
    for (i = 0; i < (int) pDexFile->pHeader->classDefsSize; i++) {
        dumpClass(pDexFile, i);
    }

    result = 0;

bail:
    if (mapped)
        sysReleaseShmem(&map);
    if (pDexFile != NULL)
        dexFileFree(pDexFile);
    return result;
}


/*
 * Show usage.
 */
void usage(void)
{
    fprintf(stderr, "Copyright (C) 2007 The Android Open Source Project\n\n");
    fprintf(stderr, "%s: dexfile [dexfile2 ...]\n", gProgName);
    fprintf(stderr, "\n");
}

/*
 * Parse args.
 */
int main(int argc, char* const argv[])
{
    int result = 0;
    int i;

    /*
     * Find all instances of the fully-qualified method name.  This isn't
     * really what dexlist is for, but it's easy to do it here.
     */
    if (argc > 3 && strcmp(argv[1], "--method") == 0) {
        gParms.argCopy = strdup(argv[2]);
        char* meth = strrchr(gParms.argCopy, '.');
        if (meth == NULL) {
            fprintf(stderr, "Expected package.Class.method\n");
            free(gParms.argCopy);
            return 2;
        }
        *meth = '\0';
        gParms.classToFind = gParms.argCopy;
        gParms.methodToFind = meth+1;
        argv += 2;
        argc -= 2;
    }

    if (argc < 2) {
        fprintf(stderr, "%s: no file specified\n", gProgName);
        usage();
        return 2;
    }

    /*
     * Run through the list of files.  If one of them fails we contine on,
     * only returning a failure at the end.
     */
    for (i = 1; i < argc; i++)
        result |= process(argv[i]);

    free(gParms.argCopy);
    return result;
}
