Home | History | Annotate | Download | only in dexdump
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * The "dexdump" tool is intended to mimic "objdump".  When possible, use
     19  * similar command-line arguments.
     20  *
     21  * TODO: rework the "plain" output format to be more regexp-friendly
     22  *
     23  * Differences between XML output and the "current.xml" file:
     24  * - classes in same package are not all grouped together; generally speaking
     25  *   nothing is sorted
     26  * - no "deprecated" on fields and methods
     27  * - no "value" on fields
     28  * - no parameter names
     29  * - no generic signatures on parameters, e.g. type="java.lang.Class<?>"
     30  * - class shows declared fields and methods; does not show inherited fields
     31  */
     32 
     33 #include "libdex/DexFile.h"
     34 
     35 #include "libdex/CmdUtils.h"
     36 #include "libdex/DexCatch.h"
     37 #include "libdex/DexClass.h"
     38 #include "libdex/DexDebugInfo.h"
     39 #include "libdex/DexOpcodes.h"
     40 #include "libdex/DexProto.h"
     41 #include "libdex/InstrUtils.h"
     42 #include "libdex/SysUtil.h"
     43 
     44 #include <stdlib.h>
     45 #include <stdio.h>
     46 #include <fcntl.h>
     47 #include <string.h>
     48 #include <unistd.h>
     49 #include <getopt.h>
     50 #include <errno.h>
     51 #include <assert.h>
     52 #include <inttypes.h>
     53 
     54 static const char* gProgName = "dexdump";
     55 
     56 enum OutputFormat {
     57     OUTPUT_PLAIN = 0,               /* default */
     58     OUTPUT_XML,                     /* fancy */
     59 };
     60 
     61 /* command-line options */
     62 struct Options {
     63     bool checksumOnly;
     64     bool disassemble;
     65     bool showFileHeaders;
     66     bool showSectionHeaders;
     67     bool ignoreBadChecksum;
     68     bool dumpRegisterMaps;
     69     OutputFormat outputFormat;
     70     const char* tempFileName;
     71     bool exportsOnly;
     72     bool verbose;
     73 };
     74 
     75 struct Options gOptions;
     76 
     77 /* basic info about a field or method */
     78 struct FieldMethodInfo {
     79     const char* classDescriptor;
     80     const char* name;
     81     const char* signature;
     82 };
     83 
     84 
     85 /* basic info about a prototype */
     86 struct ProtoInfo {
     87     char* parameterTypes;  // dynamically allocated with malloc
     88     const char* returnType;
     89 };
     90 
     91 /*
     92  * Get 2 little-endian bytes.
     93  */
     94 static inline u2 get2LE(unsigned char const* pSrc)
     95 {
     96     return pSrc[0] | (pSrc[1] << 8);
     97 }
     98 
     99 /*
    100  * Get 4 little-endian bytes.
    101  */
    102 static inline u4 get4LE(unsigned char const* pSrc)
    103 {
    104     return pSrc[0] | (pSrc[1] << 8) | (pSrc[2] << 16) | (pSrc[3] << 24);
    105 }
    106 
    107 /*
    108  * Converts a single-character primitive type into its human-readable
    109  * equivalent.
    110  */
    111 static const char* primitiveTypeLabel(char typeChar)
    112 {
    113     switch (typeChar) {
    114     case 'B':   return "byte";
    115     case 'C':   return "char";
    116     case 'D':   return "double";
    117     case 'F':   return "float";
    118     case 'I':   return "int";
    119     case 'J':   return "long";
    120     case 'S':   return "short";
    121     case 'V':   return "void";
    122     case 'Z':   return "boolean";
    123     default:
    124                 return "UNKNOWN";
    125     }
    126 }
    127 
    128 /*
    129  * Converts a type descriptor to human-readable "dotted" form.  For
    130  * example, "Ljava/lang/String;" becomes "java.lang.String", and
    131  * "[I" becomes "int[]".  Also converts '$' to '.', which means this
    132  * form can't be converted back to a descriptor.
    133  */
    134 static char* descriptorToDot(const char* str)
    135 {
    136     int targetLen = strlen(str);
    137     int offset = 0;
    138     int arrayDepth = 0;
    139     char* newStr;
    140 
    141     /* strip leading [s; will be added to end */
    142     while (targetLen > 1 && str[offset] == '[') {
    143         offset++;
    144         targetLen--;
    145     }
    146     arrayDepth = offset;
    147 
    148     if (targetLen == 1) {
    149         /* primitive type */
    150         str = primitiveTypeLabel(str[offset]);
    151         offset = 0;
    152         targetLen = strlen(str);
    153     } else {
    154         /* account for leading 'L' and trailing ';' */
    155         if (targetLen >= 2 && str[offset] == 'L' &&
    156             str[offset+targetLen-1] == ';')
    157         {
    158             targetLen -= 2;
    159             offset++;
    160         }
    161     }
    162 
    163     newStr = (char*)malloc(targetLen + arrayDepth * 2 +1);
    164 
    165     /* copy class name over */
    166     int i;
    167     for (i = 0; i < targetLen; i++) {
    168         char ch = str[offset + i];
    169         newStr[i] = (ch == '/' || ch == '$') ? '.' : ch;
    170     }
    171 
    172     /* add the appropriate number of brackets for arrays */
    173     while (arrayDepth-- > 0) {
    174         newStr[i++] = '[';
    175         newStr[i++] = ']';
    176     }
    177     newStr[i] = '\0';
    178     assert(i == targetLen + arrayDepth * 2);
    179 
    180     return newStr;
    181 }
    182 
    183 /*
    184  * Converts the class name portion of a type descriptor to human-readable
    185  * "dotted" form.
    186  *
    187  * Returns a newly-allocated string.
    188  */
    189 static char* descriptorClassToDot(const char* str)
    190 {
    191     const char* lastSlash;
    192     char* newStr;
    193     char* cp;
    194 
    195     /* reduce to just the class name, trimming trailing ';' */
    196     lastSlash = strrchr(str, '/');
    197     if (lastSlash == NULL)
    198         lastSlash = str + 1;        /* start past 'L' */
    199     else
    200         lastSlash++;                /* start past '/' */
    201 
    202     newStr = strdup(lastSlash);
    203     newStr[strlen(lastSlash)-1] = '\0';
    204     for (cp = newStr; *cp != '\0'; cp++) {
    205         if (*cp == '$')
    206             *cp = '.';
    207     }
    208 
    209     return newStr;
    210 }
    211 
    212 /*
    213  * Returns a quoted string representing the boolean value.
    214  */
    215 static const char* quotedBool(bool val)
    216 {
    217     if (val)
    218         return "\"true\"";
    219     else
    220         return "\"false\"";
    221 }
    222 
    223 static const char* quotedVisibility(u4 accessFlags)
    224 {
    225     if ((accessFlags & ACC_PUBLIC) != 0)
    226         return "\"public\"";
    227     else if ((accessFlags & ACC_PROTECTED) != 0)
    228         return "\"protected\"";
    229     else if ((accessFlags & ACC_PRIVATE) != 0)
    230         return "\"private\"";
    231     else
    232         return "\"package\"";
    233 }
    234 
    235 /*
    236  * Count the number of '1' bits in a word.
    237  */
    238 static int countOnes(u4 val)
    239 {
    240     int count = 0;
    241 
    242     val = val - ((val >> 1) & 0x55555555);
    243     val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
    244     count = (((val + (val >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
    245 
    246     return count;
    247 }
    248 
    249 /*
    250  * Flag for use with createAccessFlagStr().
    251  */
    252 enum AccessFor {
    253     kAccessForClass = 0, kAccessForMethod = 1, kAccessForField = 2,
    254     kAccessForMAX
    255 };
    256 
    257 /*
    258  * Create a new string with human-readable access flags.
    259  *
    260  * In the base language the access_flags fields are type u2; in Dalvik
    261  * they're u4.
    262  */
    263 static char* createAccessFlagStr(u4 flags, AccessFor forWhat)
    264 {
    265 #define NUM_FLAGS   18
    266     static const char* kAccessStrings[kAccessForMAX][NUM_FLAGS] = {
    267         {
    268             /* class, inner class */
    269             "PUBLIC",           /* 0x0001 */
    270             "PRIVATE",          /* 0x0002 */
    271             "PROTECTED",        /* 0x0004 */
    272             "STATIC",           /* 0x0008 */
    273             "FINAL",            /* 0x0010 */
    274             "?",                /* 0x0020 */
    275             "?",                /* 0x0040 */
    276             "?",                /* 0x0080 */
    277             "?",                /* 0x0100 */
    278             "INTERFACE",        /* 0x0200 */
    279             "ABSTRACT",         /* 0x0400 */
    280             "?",                /* 0x0800 */
    281             "SYNTHETIC",        /* 0x1000 */
    282             "ANNOTATION",       /* 0x2000 */
    283             "ENUM",             /* 0x4000 */
    284             "?",                /* 0x8000 */
    285             "VERIFIED",         /* 0x10000 */
    286             "OPTIMIZED",        /* 0x20000 */
    287         },
    288         {
    289             /* method */
    290             "PUBLIC",           /* 0x0001 */
    291             "PRIVATE",          /* 0x0002 */
    292             "PROTECTED",        /* 0x0004 */
    293             "STATIC",           /* 0x0008 */
    294             "FINAL",            /* 0x0010 */
    295             "SYNCHRONIZED",     /* 0x0020 */
    296             "BRIDGE",           /* 0x0040 */
    297             "VARARGS",          /* 0x0080 */
    298             "NATIVE",           /* 0x0100 */
    299             "?",                /* 0x0200 */
    300             "ABSTRACT",         /* 0x0400 */
    301             "STRICT",           /* 0x0800 */
    302             "SYNTHETIC",        /* 0x1000 */
    303             "?",                /* 0x2000 */
    304             "?",                /* 0x4000 */
    305             "MIRANDA",          /* 0x8000 */
    306             "CONSTRUCTOR",      /* 0x10000 */
    307             "DECLARED_SYNCHRONIZED", /* 0x20000 */
    308         },
    309         {
    310             /* field */
    311             "PUBLIC",           /* 0x0001 */
    312             "PRIVATE",          /* 0x0002 */
    313             "PROTECTED",        /* 0x0004 */
    314             "STATIC",           /* 0x0008 */
    315             "FINAL",            /* 0x0010 */
    316             "?",                /* 0x0020 */
    317             "VOLATILE",         /* 0x0040 */
    318             "TRANSIENT",        /* 0x0080 */
    319             "?",                /* 0x0100 */
    320             "?",                /* 0x0200 */
    321             "?",                /* 0x0400 */
    322             "?",                /* 0x0800 */
    323             "SYNTHETIC",        /* 0x1000 */
    324             "?",                /* 0x2000 */
    325             "ENUM",             /* 0x4000 */
    326             "?",                /* 0x8000 */
    327             "?",                /* 0x10000 */
    328             "?",                /* 0x20000 */
    329         },
    330     };
    331     const int kLongest = 21;        /* strlen of longest string above */
    332     int i, count;
    333     char* str;
    334     char* cp;
    335 
    336     /*
    337      * Allocate enough storage to hold the expected number of strings,
    338      * plus a space between each.  We over-allocate, using the longest
    339      * string above as the base metric.
    340      */
    341     count = countOnes(flags);
    342     cp = str = (char*) malloc(count * (kLongest+1) +1);
    343 
    344     for (i = 0; i < NUM_FLAGS; i++) {
    345         if (flags & 0x01) {
    346             const char* accessStr = kAccessStrings[forWhat][i];
    347             int len = strlen(accessStr);
    348             if (cp != str)
    349                 *cp++ = ' ';
    350 
    351             memcpy(cp, accessStr, len);
    352             cp += len;
    353         }
    354         flags >>= 1;
    355     }
    356     *cp = '\0';
    357 
    358     return str;
    359 }
    360 
    361 
    362 /*
    363  * Copy character data from "data" to "out", converting non-ASCII values
    364  * to printf format chars or an ASCII filler ('.' or '?').
    365  *
    366  * The output buffer must be able to hold (2*len)+1 bytes.  The result is
    367  * NUL-terminated.
    368  */
    369 static void asciify(char* out, const unsigned char* data, size_t len)
    370 {
    371     while (len--) {
    372         if (*data < 0x20) {
    373             /* could do more here, but we don't need them yet */
    374             switch (*data) {
    375             case '\0':
    376                 *out++ = '\\';
    377                 *out++ = '0';
    378                 break;
    379             case '\n':
    380                 *out++ = '\\';
    381                 *out++ = 'n';
    382                 break;
    383             default:
    384                 *out++ = '.';
    385                 break;
    386             }
    387         } else if (*data >= 0x80) {
    388             *out++ = '?';
    389         } else {
    390             *out++ = *data;
    391         }
    392         data++;
    393     }
    394     *out = '\0';
    395 }
    396 
    397 /*
    398  * Dump the file header.
    399  */
    400 void dumpFileHeader(const DexFile* pDexFile)
    401 {
    402     const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
    403     const DexHeader* pHeader = pDexFile->pHeader;
    404     char sanitized[sizeof(pHeader->magic)*2 +1];
    405 
    406     assert(sizeof(pHeader->magic) == sizeof(pOptHeader->magic));
    407 
    408     if (pOptHeader != NULL) {
    409         printf("Optimized DEX file header:\n");
    410 
    411         asciify(sanitized, pOptHeader->magic, sizeof(pOptHeader->magic));
    412         printf("magic               : '%s'\n", sanitized);
    413         printf("dex_offset          : %d (0x%06x)\n",
    414             pOptHeader->dexOffset, pOptHeader->dexOffset);
    415         printf("dex_length          : %d\n", pOptHeader->dexLength);
    416         printf("deps_offset         : %d (0x%06x)\n",
    417             pOptHeader->depsOffset, pOptHeader->depsOffset);
    418         printf("deps_length         : %d\n", pOptHeader->depsLength);
    419         printf("opt_offset          : %d (0x%06x)\n",
    420             pOptHeader->optOffset, pOptHeader->optOffset);
    421         printf("opt_length          : %d\n", pOptHeader->optLength);
    422         printf("flags               : %08x\n", pOptHeader->flags);
    423         printf("checksum            : %08x\n", pOptHeader->checksum);
    424         printf("\n");
    425     }
    426 
    427     printf("DEX file header:\n");
    428     asciify(sanitized, pHeader->magic, sizeof(pHeader->magic));
    429     printf("magic               : '%s'\n", sanitized);
    430     printf("checksum            : %08x\n", pHeader->checksum);
    431     printf("signature           : %02x%02x...%02x%02x\n",
    432         pHeader->signature[0], pHeader->signature[1],
    433         pHeader->signature[kSHA1DigestLen-2],
    434         pHeader->signature[kSHA1DigestLen-1]);
    435     printf("file_size           : %d\n", pHeader->fileSize);
    436     printf("header_size         : %d\n", pHeader->headerSize);
    437     printf("link_size           : %d\n", pHeader->linkSize);
    438     printf("link_off            : %d (0x%06x)\n",
    439         pHeader->linkOff, pHeader->linkOff);
    440     printf("string_ids_size     : %d\n", pHeader->stringIdsSize);
    441     printf("string_ids_off      : %d (0x%06x)\n",
    442         pHeader->stringIdsOff, pHeader->stringIdsOff);
    443     printf("type_ids_size       : %d\n", pHeader->typeIdsSize);
    444     printf("type_ids_off        : %d (0x%06x)\n",
    445         pHeader->typeIdsOff, pHeader->typeIdsOff);
    446     printf("proto_ids_size       : %d\n", pHeader->protoIdsSize);
    447     printf("proto_ids_off        : %d (0x%06x)\n",
    448         pHeader->protoIdsOff, pHeader->protoIdsOff);
    449     printf("field_ids_size      : %d\n", pHeader->fieldIdsSize);
    450     printf("field_ids_off       : %d (0x%06x)\n",
    451         pHeader->fieldIdsOff, pHeader->fieldIdsOff);
    452     printf("method_ids_size     : %d\n", pHeader->methodIdsSize);
    453     printf("method_ids_off      : %d (0x%06x)\n",
    454         pHeader->methodIdsOff, pHeader->methodIdsOff);
    455     printf("class_defs_size     : %d\n", pHeader->classDefsSize);
    456     printf("class_defs_off      : %d (0x%06x)\n",
    457         pHeader->classDefsOff, pHeader->classDefsOff);
    458     printf("data_size           : %d\n", pHeader->dataSize);
    459     printf("data_off            : %d (0x%06x)\n",
    460         pHeader->dataOff, pHeader->dataOff);
    461     printf("\n");
    462 }
    463 
    464 /*
    465  * Dump the "table of contents" for the opt area.
    466  */
    467 void dumpOptDirectory(const DexFile* pDexFile)
    468 {
    469     const DexOptHeader* pOptHeader = pDexFile->pOptHeader;
    470     if (pOptHeader == NULL)
    471         return;
    472 
    473     printf("OPT section contents:\n");
    474 
    475     const u4* pOpt = (const u4*) ((u1*) pOptHeader + pOptHeader->optOffset);
    476 
    477     if (*pOpt == 0) {
    478         printf("(1.0 format, only class lookup table is present)\n\n");
    479         return;
    480     }
    481 
    482     /*
    483      * The "opt" section is in "chunk" format: a 32-bit identifier, a 32-bit
    484      * length, then the data.  Chunks start on 64-bit boundaries.
    485      */
    486     while (*pOpt != kDexChunkEnd) {
    487         const char* verboseStr;
    488 
    489         u4 size = *(pOpt+1);
    490 
    491         switch (*pOpt) {
    492         case kDexChunkClassLookup:
    493             verboseStr = "class lookup hash table";
    494             break;
    495         case kDexChunkRegisterMaps:
    496             verboseStr = "register maps";
    497             break;
    498         default:
    499             verboseStr = "(unknown chunk type)";
    500             break;
    501         }
    502 
    503         printf("Chunk %08x (%c%c%c%c) - %s (%d bytes)\n", *pOpt,
    504             *pOpt >> 24, (char)(*pOpt >> 16), (char)(*pOpt >> 8), (char)*pOpt,
    505             verboseStr, size);
    506 
    507         size = (size + 8 + 7) & ~7;
    508         pOpt += size / sizeof(u4);
    509     }
    510     printf("\n");
    511 }
    512 
    513 /*
    514  * Dump a class_def_item.
    515  */
    516 void dumpClassDef(DexFile* pDexFile, int idx)
    517 {
    518     const DexClassDef* pClassDef;
    519     const u1* pEncodedData;
    520     DexClassData* pClassData;
    521 
    522     pClassDef = dexGetClassDef(pDexFile, idx);
    523     pEncodedData = dexGetClassData(pDexFile, pClassDef);
    524     pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
    525 
    526     if (pClassData == NULL) {
    527         fprintf(stderr, "Trouble reading class data\n");
    528         return;
    529     }
    530 
    531     printf("Class #%d header:\n", idx);
    532     printf("class_idx           : %d\n", pClassDef->classIdx);
    533     printf("access_flags        : %d (0x%04x)\n",
    534         pClassDef->accessFlags, pClassDef->accessFlags);
    535     printf("superclass_idx      : %d\n", pClassDef->superclassIdx);
    536     printf("interfaces_off      : %d (0x%06x)\n",
    537         pClassDef->interfacesOff, pClassDef->interfacesOff);
    538     printf("source_file_idx     : %d\n", pClassDef->sourceFileIdx);
    539     printf("annotations_off     : %d (0x%06x)\n",
    540         pClassDef->annotationsOff, pClassDef->annotationsOff);
    541     printf("class_data_off      : %d (0x%06x)\n",
    542         pClassDef->classDataOff, pClassDef->classDataOff);
    543     printf("static_fields_size  : %d\n", pClassData->header.staticFieldsSize);
    544     printf("instance_fields_size: %d\n",
    545             pClassData->header.instanceFieldsSize);
    546     printf("direct_methods_size : %d\n", pClassData->header.directMethodsSize);
    547     printf("virtual_methods_size: %d\n",
    548             pClassData->header.virtualMethodsSize);
    549     printf("\n");
    550 
    551     free(pClassData);
    552 }
    553 
    554 /*
    555  * Dump an interface that a class declares to implement.
    556  */
    557 void dumpInterface(const DexFile* pDexFile, const DexTypeItem* pTypeItem,
    558     int i)
    559 {
    560     const char* interfaceName =
    561         dexStringByTypeIdx(pDexFile, pTypeItem->typeIdx);
    562 
    563     if (gOptions.outputFormat == OUTPUT_PLAIN) {
    564         printf("    #%d              : '%s'\n", i, interfaceName);
    565     } else {
    566         char* dotted = descriptorToDot(interfaceName);
    567         printf("<implements name=\"%s\">\n</implements>\n", dotted);
    568         free(dotted);
    569     }
    570 }
    571 
    572 /*
    573  * Dump the catches table associated with the code.
    574  */
    575 void dumpCatches(DexFile* pDexFile, const DexCode* pCode)
    576 {
    577     u4 triesSize = pCode->triesSize;
    578 
    579     if (triesSize == 0) {
    580         printf("      catches       : (none)\n");
    581         return;
    582     }
    583 
    584     printf("      catches       : %d\n", triesSize);
    585 
    586     const DexTry* pTries = dexGetTries(pCode);
    587     u4 i;
    588 
    589     for (i = 0; i < triesSize; i++) {
    590         const DexTry* pTry = &pTries[i];
    591         u4 start = pTry->startAddr;
    592         u4 end = start + pTry->insnCount;
    593         DexCatchIterator iterator;
    594 
    595         printf("        0x%04x - 0x%04x\n", start, end);
    596 
    597         dexCatchIteratorInit(&iterator, pCode, pTry->handlerOff);
    598 
    599         for (;;) {
    600             DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
    601             const char* descriptor;
    602 
    603             if (handler == NULL) {
    604                 break;
    605             }
    606 
    607             descriptor = (handler->typeIdx == kDexNoIndex) ? "<any>" :
    608                 dexStringByTypeIdx(pDexFile, handler->typeIdx);
    609 
    610             printf("          %s -> 0x%04x\n", descriptor,
    611                     handler->address);
    612         }
    613     }
    614 }
    615 
    616 static int dumpPositionsCb(void * /* cnxt */, u4 address, u4 lineNum)
    617 {
    618     printf("        0x%04x line=%d\n", address, lineNum);
    619     return 0;
    620 }
    621 
    622 /*
    623  * Dump the positions list.
    624  */
    625 void dumpPositions(DexFile* pDexFile, const DexCode* pCode,
    626         const DexMethod *pDexMethod)
    627 {
    628     printf("      positions     : \n");
    629     const DexMethodId *pMethodId
    630             = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
    631     const char *classDescriptor
    632             = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
    633 
    634     dexDecodeDebugInfo(pDexFile, pCode, classDescriptor, pMethodId->protoIdx,
    635             pDexMethod->accessFlags, dumpPositionsCb, NULL, NULL);
    636 }
    637 
    638 static void dumpLocalsCb(void * /* cnxt */, u2 reg, u4 startAddress,
    639         u4 endAddress, const char *name, const char *descriptor,
    640         const char *signature)
    641 {
    642     printf("        0x%04x - 0x%04x reg=%d %s %s %s\n",
    643             startAddress, endAddress, reg, name, descriptor,
    644             signature);
    645 }
    646 
    647 /*
    648  * Dump the locals list.
    649  */
    650 void dumpLocals(DexFile* pDexFile, const DexCode* pCode,
    651         const DexMethod *pDexMethod)
    652 {
    653     printf("      locals        : \n");
    654 
    655     const DexMethodId *pMethodId
    656             = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
    657     const char *classDescriptor
    658             = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
    659 
    660     dexDecodeDebugInfo(pDexFile, pCode, classDescriptor, pMethodId->protoIdx,
    661             pDexMethod->accessFlags, NULL, dumpLocalsCb, NULL);
    662 }
    663 
    664 /*
    665  * Get information about a method.
    666  */
    667 bool getMethodInfo(DexFile* pDexFile, u4 methodIdx, FieldMethodInfo* pMethInfo)
    668 {
    669     const DexMethodId* pMethodId;
    670 
    671     if (methodIdx >= pDexFile->pHeader->methodIdsSize)
    672         return false;
    673 
    674     pMethodId = dexGetMethodId(pDexFile, methodIdx);
    675     pMethInfo->name = dexStringById(pDexFile, pMethodId->nameIdx);
    676     pMethInfo->signature = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
    677 
    678     pMethInfo->classDescriptor =
    679             dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
    680     return true;
    681 }
    682 
    683 /*
    684  * Get information about a field.
    685  */
    686 bool getFieldInfo(DexFile* pDexFile, u4 fieldIdx, FieldMethodInfo* pFieldInfo)
    687 {
    688     const DexFieldId* pFieldId;
    689 
    690     if (fieldIdx >= pDexFile->pHeader->fieldIdsSize)
    691         return false;
    692 
    693     pFieldId = dexGetFieldId(pDexFile, fieldIdx);
    694     pFieldInfo->name = dexStringById(pDexFile, pFieldId->nameIdx);
    695     pFieldInfo->signature = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
    696     pFieldInfo->classDescriptor =
    697         dexStringByTypeIdx(pDexFile, pFieldId->classIdx);
    698     return true;
    699 }
    700 
    701 /*
    702  * Get information about a ProtoId.
    703  */
    704 bool getProtoInfo(DexFile* pDexFile, u4 protoIdx, ProtoInfo* pProtoInfo)
    705 {
    706     if (protoIdx >= pDexFile->pHeader->protoIdsSize) {
    707         return false;
    708     }
    709 
    710     const DexProtoId* protoId = dexGetProtoId(pDexFile, protoIdx);
    711 
    712     // Get string for return type.
    713     if (protoId->returnTypeIdx >= pDexFile->pHeader->typeIdsSize) {
    714         return false;
    715     }
    716     pProtoInfo->returnType = dexStringByTypeIdx(pDexFile, protoId->returnTypeIdx);
    717 
    718     // Build string for parameter types.
    719     size_t bufSize = 1;
    720     char* buf = (char*)malloc(bufSize);
    721     if (buf == NULL) {
    722         return false;
    723     }
    724 
    725     buf[0] = '\0';
    726     size_t bufUsed = 1;
    727 
    728     const DexTypeList* paramTypes = dexGetProtoParameters(pDexFile, protoId);
    729     if (paramTypes == NULL) {
    730         // No parameters.
    731         pProtoInfo->parameterTypes = buf;
    732         return true;
    733     }
    734 
    735     for (u4 i = 0; i < paramTypes->size; ++i) {
    736         if (paramTypes->list[i].typeIdx >= pDexFile->pHeader->typeIdsSize) {
    737             free(buf);
    738             return false;
    739         }
    740         const char* param = dexStringByTypeIdx(pDexFile, paramTypes->list[i].typeIdx);
    741         size_t newUsed = bufUsed + strlen(param);
    742         if (newUsed > bufSize) {
    743             char* newBuf = (char*)realloc(buf, newUsed);
    744             if (newBuf == NULL) {
    745                 free(buf);
    746                 return false;
    747             }
    748             buf = newBuf;
    749             bufSize = newUsed;
    750         }
    751         strncat(buf + bufUsed - 1, param, bufSize - (bufUsed - 1));
    752         bufUsed = newUsed;
    753     }
    754 
    755     pProtoInfo->parameterTypes = buf;
    756     return true;
    757 }
    758 
    759 /*
    760  * Look up a class' descriptor.
    761  */
    762 const char* getClassDescriptor(DexFile* pDexFile, u4 classIdx)
    763 {
    764     return dexStringByTypeIdx(pDexFile, classIdx);
    765 }
    766 
    767 /*
    768  * Helper for dumpInstruction(), which builds the string
    769  * representation for the index in the given instruction. This will
    770  * first try to use the given buffer, but if the result won't fit,
    771  * then this will allocate a new buffer to hold the result. A pointer
    772  * to the buffer which holds the full result is always returned, and
    773  * this can be compared with the one passed in, to see if the result
    774  * needs to be free()d.
    775  */
    776 static char* indexString(DexFile* pDexFile, const DecodedInstruction* pDecInsn, size_t bufSize)
    777 {
    778     char* buf = (char*)malloc(bufSize);
    779     if (buf == NULL) {
    780       return NULL;
    781     }
    782 
    783     int outSize;
    784     u4 index;
    785     u4 secondaryIndex = 0;
    786     u4 width;
    787 
    788     /* TODO: Make the index *always* be in field B, to simplify this code. */
    789     switch (dexGetFormatFromOpcode(pDecInsn->opcode)) {
    790     case kFmt20bc:
    791     case kFmt21c:
    792     case kFmt35c:
    793     case kFmt35ms:
    794     case kFmt3rc:
    795     case kFmt3rms:
    796     case kFmt35mi:
    797     case kFmt3rmi:
    798         index = pDecInsn->vB;
    799         width = 4;
    800         break;
    801     case kFmt31c:
    802         index = pDecInsn->vB;
    803         width = 8;
    804         break;
    805     case kFmt22c:
    806     case kFmt22cs:
    807         index = pDecInsn->vC;
    808         width = 4;
    809         break;
    810     case kFmt45cc:
    811     case kFmt4rcc:
    812         index = pDecInsn->vB;  // method index
    813         secondaryIndex = pDecInsn->arg[4];  // proto index
    814         width = 4;
    815         break;
    816     default:
    817         index = 0;
    818         width = 4;
    819         break;
    820     }
    821 
    822     switch (pDecInsn->indexType) {
    823     case kIndexUnknown:
    824         /*
    825          * This function shouldn't ever get called for this type, but do
    826          * something sensible here, just to help with debugging.
    827          */
    828         outSize = snprintf(buf, bufSize, "<unknown-index>");
    829         break;
    830     case kIndexNone:
    831         /*
    832          * This function shouldn't ever get called for this type, but do
    833          * something sensible here, just to help with debugging.
    834          */
    835         outSize = snprintf(buf, bufSize, "<no-index>");
    836         break;
    837     case kIndexVaries:
    838         /*
    839          * This one should never show up in a dexdump, so no need to try
    840          * to get fancy here.
    841          */
    842         outSize = snprintf(buf, bufSize, "<index-varies> // thing@%0*x",
    843                 width, index);
    844         break;
    845     case kIndexTypeRef:
    846         if (index < pDexFile->pHeader->typeIdsSize) {
    847             outSize = snprintf(buf, bufSize, "%s // type@%0*x",
    848                                getClassDescriptor(pDexFile, index), width, index);
    849         } else {
    850             outSize = snprintf(buf, bufSize, "<type?> // type@%0*x", width, index);
    851         }
    852         break;
    853     case kIndexStringRef:
    854         if (index < pDexFile->pHeader->stringIdsSize) {
    855             outSize = snprintf(buf, bufSize, "\"%s\" // string@%0*x",
    856                                dexStringById(pDexFile, index), width, index);
    857         } else {
    858             outSize = snprintf(buf, bufSize, "<string?> // string@%0*x",
    859                                width, index);
    860         }
    861         break;
    862     case kIndexMethodRef:
    863         {
    864             FieldMethodInfo methInfo;
    865             if (getMethodInfo(pDexFile, index, &methInfo)) {
    866                 outSize = snprintf(buf, bufSize, "%s.%s:%s // method@%0*x",
    867                         methInfo.classDescriptor, methInfo.name,
    868                         methInfo.signature, width, index);
    869                 free((void *) methInfo.signature);
    870             } else {
    871                 outSize = snprintf(buf, bufSize, "<method?> // method@%0*x",
    872                         width, index);
    873             }
    874         }
    875         break;
    876     case kIndexFieldRef:
    877         {
    878             FieldMethodInfo fieldInfo;
    879             if (getFieldInfo(pDexFile, index, &fieldInfo)) {
    880                 outSize = snprintf(buf, bufSize, "%s.%s:%s // field@%0*x",
    881                         fieldInfo.classDescriptor, fieldInfo.name,
    882                         fieldInfo.signature, width, index);
    883             } else {
    884                 outSize = snprintf(buf, bufSize, "<field?> // field@%0*x",
    885                         width, index);
    886             }
    887         }
    888         break;
    889     case kIndexInlineMethod:
    890         outSize = snprintf(buf, bufSize, "[%0*x] // inline #%0*x",
    891                 width, index, width, index);
    892         break;
    893     case kIndexVtableOffset:
    894         outSize = snprintf(buf, bufSize, "[%0*x] // vtable #%0*x",
    895                 width, index, width, index);
    896         break;
    897     case kIndexFieldOffset:
    898         outSize = snprintf(buf, bufSize, "[obj+%0*x]", width, index);
    899         break;
    900     case kIndexMethodAndProtoRef:
    901         {
    902             FieldMethodInfo methInfo;
    903             ProtoInfo protoInfo;
    904             protoInfo.parameterTypes = NULL;
    905             if (getMethodInfo(pDexFile, index, &methInfo) &&
    906                 getProtoInfo(pDexFile, secondaryIndex, &protoInfo)) {
    907                 outSize = snprintf(buf, bufSize, "%s.%s:%s, (%s)%s // method@%0*x, proto@%0*x",
    908                                    methInfo.classDescriptor, methInfo.name, methInfo.signature,
    909                                    protoInfo.parameterTypes, protoInfo.returnType,
    910                                    width, index, width, secondaryIndex);
    911             } else {
    912                 outSize = snprintf(buf, bufSize, "<method?>, <proto?> // method@%0*x, proto@%0*x",
    913                                    width, index, width, secondaryIndex);
    914             }
    915             free(protoInfo.parameterTypes);
    916         }
    917         break;
    918     case kCallSiteRef:
    919         outSize = snprintf(buf, bufSize, "call_site@%0*x", width, index);
    920         break;
    921     default:
    922         outSize = snprintf(buf, bufSize, "<?>");
    923         break;
    924     }
    925 
    926     if (outSize >= (int) bufSize) {
    927         /*
    928          * The buffer wasn't big enough; allocate and retry. Note:
    929          * snprintf() doesn't count the '\0' as part of its returned
    930          * size, so we add explicit space for it here.
    931          */
    932         free(buf);
    933         return indexString(pDexFile, pDecInsn, outSize + 1);
    934     } else {
    935         return buf;
    936     }
    937 }
    938 
    939 /*
    940  * Dump a single instruction.
    941  */
    942 void dumpInstruction(DexFile* pDexFile, const DexCode* pCode, int insnIdx,
    943     int insnWidth, const DecodedInstruction* pDecInsn)
    944 {
    945     const u2* insns = pCode->insns;
    946     int i;
    947 
    948     // Address of instruction (expressed as byte offset).
    949     printf("%06zx:", ((u1*)insns - pDexFile->baseAddr) + insnIdx*2);
    950 
    951     for (i = 0; i < 8; i++) {
    952         if (i < insnWidth) {
    953             if (i == 7) {
    954                 printf(" ... ");
    955             } else {
    956                 /* print 16-bit value in little-endian order */
    957                 const u1* bytePtr = (const u1*) &insns[insnIdx+i];
    958                 printf(" %02x%02x", bytePtr[0], bytePtr[1]);
    959             }
    960         } else {
    961             fputs("     ", stdout);
    962         }
    963     }
    964 
    965     if (pDecInsn->opcode == OP_NOP) {
    966         u2 instr = get2LE((const u1*) &insns[insnIdx]);
    967         if (instr == kPackedSwitchSignature) {
    968             printf("|%04x: packed-switch-data (%d units)",
    969                 insnIdx, insnWidth);
    970         } else if (instr == kSparseSwitchSignature) {
    971             printf("|%04x: sparse-switch-data (%d units)",
    972                 insnIdx, insnWidth);
    973         } else if (instr == kArrayDataSignature) {
    974             printf("|%04x: array-data (%d units)",
    975                 insnIdx, insnWidth);
    976         } else {
    977             printf("|%04x: nop // spacer", insnIdx);
    978         }
    979     } else {
    980         printf("|%04x: %s", insnIdx, dexGetOpcodeName(pDecInsn->opcode));
    981     }
    982 
    983     // Provide an initial buffer that usually suffices, although indexString()
    984     // may reallocate the buffer if more space is needed.
    985     char* indexBuf = NULL;
    986     if (pDecInsn->indexType != kIndexNone) {
    987         indexBuf = indexString(pDexFile, pDecInsn, 200);
    988     }
    989 
    990     switch (dexGetFormatFromOpcode(pDecInsn->opcode)) {
    991     case kFmt10x:        // op
    992         break;
    993     case kFmt12x:        // op vA, vB
    994         printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
    995         break;
    996     case kFmt11n:        // op vA, #+B
    997         printf(" v%d, #int %d // #%x",
    998             pDecInsn->vA, (s4)pDecInsn->vB, (u1)pDecInsn->vB);
    999         break;
   1000     case kFmt11x:        // op vAA
   1001         printf(" v%d", pDecInsn->vA);
   1002         break;
   1003     case kFmt10t:        // op +AA
   1004     case kFmt20t:        // op +AAAA
   1005         {
   1006             s4 targ = (s4) pDecInsn->vA;
   1007             printf(" %04x // %c%04x",
   1008                 insnIdx + targ,
   1009                 (targ < 0) ? '-' : '+',
   1010                 (targ < 0) ? -targ : targ);
   1011         }
   1012         break;
   1013     case kFmt22x:        // op vAA, vBBBB
   1014         printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
   1015         break;
   1016     case kFmt21t:        // op vAA, +BBBB
   1017         {
   1018             s4 targ = (s4) pDecInsn->vB;
   1019             printf(" v%d, %04x // %c%04x", pDecInsn->vA,
   1020                 insnIdx + targ,
   1021                 (targ < 0) ? '-' : '+',
   1022                 (targ < 0) ? -targ : targ);
   1023         }
   1024         break;
   1025     case kFmt21s:        // op vAA, #+BBBB
   1026         printf(" v%d, #int %d // #%x",
   1027             pDecInsn->vA, (s4)pDecInsn->vB, (u2)pDecInsn->vB);
   1028         break;
   1029     case kFmt21h:        // op vAA, #+BBBB0000[00000000]
   1030         // The printed format varies a bit based on the actual opcode.
   1031         if (pDecInsn->opcode == OP_CONST_HIGH16) {
   1032             s4 value = pDecInsn->vB << 16;
   1033             printf(" v%d, #int %d // #%x",
   1034                 pDecInsn->vA, value, (u2)pDecInsn->vB);
   1035         } else {
   1036             s8 value = ((s8) pDecInsn->vB) << 48;
   1037             printf(" v%d, #long %" PRId64 " // #%x",
   1038                 pDecInsn->vA, value, (u2)pDecInsn->vB);
   1039         }
   1040         break;
   1041     case kFmt21c:        // op vAA, thing@BBBB
   1042     case kFmt31c:        // op vAA, thing@BBBBBBBB
   1043         printf(" v%d, %s", pDecInsn->vA, indexBuf);
   1044         break;
   1045     case kFmt23x:        // op vAA, vBB, vCC
   1046         printf(" v%d, v%d, v%d", pDecInsn->vA, pDecInsn->vB, pDecInsn->vC);
   1047         break;
   1048     case kFmt22b:        // op vAA, vBB, #+CC
   1049         printf(" v%d, v%d, #int %d // #%02x",
   1050             pDecInsn->vA, pDecInsn->vB, (s4)pDecInsn->vC, (u1)pDecInsn->vC);
   1051         break;
   1052     case kFmt22t:        // op vA, vB, +CCCC
   1053         {
   1054             s4 targ = (s4) pDecInsn->vC;
   1055             printf(" v%d, v%d, %04x // %c%04x", pDecInsn->vA, pDecInsn->vB,
   1056                 insnIdx + targ,
   1057                 (targ < 0) ? '-' : '+',
   1058                 (targ < 0) ? -targ : targ);
   1059         }
   1060         break;
   1061     case kFmt22s:        // op vA, vB, #+CCCC
   1062         printf(" v%d, v%d, #int %d // #%04x",
   1063             pDecInsn->vA, pDecInsn->vB, (s4)pDecInsn->vC, (u2)pDecInsn->vC);
   1064         break;
   1065     case kFmt22c:        // op vA, vB, thing@CCCC
   1066     case kFmt22cs:       // [opt] op vA, vB, field offset CCCC
   1067         printf(" v%d, v%d, %s", pDecInsn->vA, pDecInsn->vB, indexBuf);
   1068         break;
   1069     case kFmt30t:
   1070         printf(" #%08x", pDecInsn->vA);
   1071         break;
   1072     case kFmt31i:        // op vAA, #+BBBBBBBB
   1073         {
   1074             /* this is often, but not always, a float */
   1075             union {
   1076                 float f;
   1077                 u4 i;
   1078             } conv;
   1079             conv.i = pDecInsn->vB;
   1080             printf(" v%d, #float %f // #%08x",
   1081                 pDecInsn->vA, conv.f, pDecInsn->vB);
   1082         }
   1083         break;
   1084     case kFmt31t:       // op vAA, offset +BBBBBBBB
   1085         printf(" v%d, %08x // +%08x",
   1086             pDecInsn->vA, insnIdx + pDecInsn->vB, pDecInsn->vB);
   1087         break;
   1088     case kFmt32x:        // op vAAAA, vBBBB
   1089         printf(" v%d, v%d", pDecInsn->vA, pDecInsn->vB);
   1090         break;
   1091     case kFmt35c:        // op {vC, vD, vE, vF, vG}, thing@BBBB
   1092     case kFmt35ms:       // [opt] invoke-virtual+super
   1093     case kFmt35mi:       // [opt] inline invoke
   1094         {
   1095             fputs(" {", stdout);
   1096             for (i = 0; i < (int) pDecInsn->vA; i++) {
   1097                 if (i == 0)
   1098                     printf("v%d", pDecInsn->arg[i]);
   1099                 else
   1100                     printf(", v%d", pDecInsn->arg[i]);
   1101             }
   1102             printf("}, %s", indexBuf);
   1103         }
   1104         break;
   1105     case kFmt3rc:        // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
   1106     case kFmt3rms:       // [opt] invoke-virtual+super/range
   1107     case kFmt3rmi:       // [opt] execute-inline/range
   1108         {
   1109             /*
   1110              * This doesn't match the "dx" output when some of the args are
   1111              * 64-bit values -- dx only shows the first register.
   1112              */
   1113             fputs(" {", stdout);
   1114             for (i = 0; i < (int) pDecInsn->vA; i++) {
   1115                 if (i == 0)
   1116                     printf("v%d", pDecInsn->vC + i);
   1117                 else
   1118                     printf(", v%d", pDecInsn->vC + i);
   1119             }
   1120             printf("}, %s", indexBuf);
   1121         }
   1122         break;
   1123     case kFmt51l:        // op vAA, #+BBBBBBBBBBBBBBBB
   1124         {
   1125             /* this is often, but not always, a double */
   1126             union {
   1127                 double d;
   1128                 u8 j;
   1129             } conv;
   1130             conv.j = pDecInsn->vB_wide;
   1131             printf(" v%d, #double %f // #%016" PRIx64,
   1132                 pDecInsn->vA, conv.d, pDecInsn->vB_wide);
   1133         }
   1134         break;
   1135     case kFmt00x:        // unknown op or breakpoint
   1136         break;
   1137     case kFmt45cc:
   1138         {
   1139             fputs("  {", stdout);
   1140             printf("v%d", pDecInsn->vC);
   1141             for (int i = 0; i < (int) pDecInsn->vA - 1; ++i) {
   1142                 printf(", v%d", pDecInsn->arg[i]);
   1143             }
   1144             printf("}, %s", indexBuf);
   1145         }
   1146         break;
   1147     case kFmt4rcc:
   1148         {
   1149             fputs("  {", stdout);
   1150             printf("v%d", pDecInsn->vC);
   1151             for (int i = 1; i < (int) pDecInsn->vA; ++i) {
   1152                 printf(", v%d", pDecInsn->vC + i);
   1153             }
   1154             printf("}, %s", indexBuf);
   1155         }
   1156         break;
   1157     default:
   1158         printf(" ???");
   1159         break;
   1160     }
   1161 
   1162     putchar('\n');
   1163 
   1164     free(indexBuf);
   1165 }
   1166 
   1167 /*
   1168  * Dump a bytecode disassembly.
   1169  */
   1170 void dumpBytecodes(DexFile* pDexFile, const DexMethod* pDexMethod)
   1171 {
   1172     const DexCode* pCode = dexGetCode(pDexFile, pDexMethod);
   1173     const u2* insns;
   1174     int insnIdx;
   1175     FieldMethodInfo methInfo;
   1176     int startAddr;
   1177     char* className = NULL;
   1178 
   1179     assert(pCode->insnsSize > 0);
   1180     insns = pCode->insns;
   1181 
   1182     methInfo.classDescriptor =
   1183     methInfo.name =
   1184     methInfo.signature = NULL;
   1185 
   1186     getMethodInfo(pDexFile, pDexMethod->methodIdx, &methInfo);
   1187     startAddr = ((u1*)pCode - pDexFile->baseAddr);
   1188     className = descriptorToDot(methInfo.classDescriptor);
   1189 
   1190     printf("%06x:                                        |[%06x] %s.%s:%s\n",
   1191         startAddr, startAddr,
   1192         className, methInfo.name, methInfo.signature);
   1193     free((void *) methInfo.signature);
   1194 
   1195     insnIdx = 0;
   1196     while (insnIdx < (int) pCode->insnsSize) {
   1197         int insnWidth;
   1198         DecodedInstruction decInsn;
   1199         u2 instr;
   1200 
   1201         /*
   1202          * Note: This code parallels the function
   1203          * dexGetWidthFromInstruction() in InstrUtils.c, but this version
   1204          * can deal with data in either endianness.
   1205          *
   1206          * TODO: Figure out if this really matters, and possibly change
   1207          * this to just use dexGetWidthFromInstruction().
   1208          */
   1209         instr = get2LE((const u1*)insns);
   1210         if (instr == kPackedSwitchSignature) {
   1211             insnWidth = 4 + get2LE((const u1*)(insns+1)) * 2;
   1212         } else if (instr == kSparseSwitchSignature) {
   1213             insnWidth = 2 + get2LE((const u1*)(insns+1)) * 4;
   1214         } else if (instr == kArrayDataSignature) {
   1215             int width = get2LE((const u1*)(insns+1));
   1216             int size = get2LE((const u1*)(insns+2)) |
   1217                        (get2LE((const u1*)(insns+3))<<16);
   1218             // The plus 1 is to round up for odd size and width.
   1219             insnWidth = 4 + ((size * width) + 1) / 2;
   1220         } else {
   1221             Opcode opcode = dexOpcodeFromCodeUnit(instr);
   1222             insnWidth = dexGetWidthFromOpcode(opcode);
   1223             if (insnWidth == 0) {
   1224                 fprintf(stderr,
   1225                     "GLITCH: zero-width instruction at idx=0x%04x\n", insnIdx);
   1226                 break;
   1227             }
   1228         }
   1229 
   1230         dexDecodeInstruction(insns, &decInsn);
   1231         dumpInstruction(pDexFile, pCode, insnIdx, insnWidth, &decInsn);
   1232 
   1233         insns += insnWidth;
   1234         insnIdx += insnWidth;
   1235     }
   1236 
   1237     free(className);
   1238 }
   1239 
   1240 /*
   1241  * Dump a "code" struct.
   1242  */
   1243 void dumpCode(DexFile* pDexFile, const DexMethod* pDexMethod)
   1244 {
   1245     const DexCode* pCode = dexGetCode(pDexFile, pDexMethod);
   1246 
   1247     printf("      registers     : %d\n", pCode->registersSize);
   1248     printf("      ins           : %d\n", pCode->insSize);
   1249     printf("      outs          : %d\n", pCode->outsSize);
   1250     printf("      insns size    : %d 16-bit code units\n", pCode->insnsSize);
   1251 
   1252     if (gOptions.disassemble)
   1253         dumpBytecodes(pDexFile, pDexMethod);
   1254 
   1255     dumpCatches(pDexFile, pCode);
   1256     /* both of these are encoded in debug info */
   1257     dumpPositions(pDexFile, pCode, pDexMethod);
   1258     dumpLocals(pDexFile, pCode, pDexMethod);
   1259 }
   1260 
   1261 /*
   1262  * Dump a method.
   1263  */
   1264 void dumpMethod(DexFile* pDexFile, const DexMethod* pDexMethod, int i)
   1265 {
   1266     const DexMethodId* pMethodId;
   1267     const char* backDescriptor;
   1268     const char* name;
   1269     char* typeDescriptor = NULL;
   1270     char* accessStr = NULL;
   1271 
   1272     if (gOptions.exportsOnly &&
   1273         (pDexMethod->accessFlags & (ACC_PUBLIC | ACC_PROTECTED)) == 0)
   1274     {
   1275         return;
   1276     }
   1277 
   1278     pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
   1279     name = dexStringById(pDexFile, pMethodId->nameIdx);
   1280     typeDescriptor = dexCopyDescriptorFromMethodId(pDexFile, pMethodId);
   1281 
   1282     backDescriptor = dexStringByTypeIdx(pDexFile, pMethodId->classIdx);
   1283 
   1284     accessStr = createAccessFlagStr(pDexMethod->accessFlags,
   1285                     kAccessForMethod);
   1286 
   1287     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1288         printf("    #%d              : (in %s)\n", i, backDescriptor);
   1289         printf("      name          : '%s'\n", name);
   1290         printf("      type          : '%s'\n", typeDescriptor);
   1291         printf("      access        : 0x%04x (%s)\n",
   1292             pDexMethod->accessFlags, accessStr);
   1293 
   1294         if (pDexMethod->codeOff == 0) {
   1295             printf("      code          : (none)\n");
   1296         } else {
   1297             printf("      code          -\n");
   1298             dumpCode(pDexFile, pDexMethod);
   1299         }
   1300 
   1301         if (gOptions.disassemble)
   1302             putchar('\n');
   1303     } else if (gOptions.outputFormat == OUTPUT_XML) {
   1304         bool constructor = (name[0] == '<');
   1305 
   1306         if (constructor) {
   1307             char* tmp;
   1308 
   1309             tmp = descriptorClassToDot(backDescriptor);
   1310             printf("<constructor name=\"%s\"\n", tmp);
   1311             free(tmp);
   1312 
   1313             tmp = descriptorToDot(backDescriptor);
   1314             printf(" type=\"%s\"\n", tmp);
   1315             free(tmp);
   1316         } else {
   1317             printf("<method name=\"%s\"\n", name);
   1318 
   1319             const char* returnType = strrchr(typeDescriptor, ')');
   1320             if (returnType == NULL) {
   1321                 fprintf(stderr, "bad method type descriptor '%s'\n",
   1322                     typeDescriptor);
   1323                 goto bail;
   1324             }
   1325 
   1326             char* tmp = descriptorToDot(returnType+1);
   1327             printf(" return=\"%s\"\n", tmp);
   1328             free(tmp);
   1329 
   1330             printf(" abstract=%s\n",
   1331                 quotedBool((pDexMethod->accessFlags & ACC_ABSTRACT) != 0));
   1332             printf(" native=%s\n",
   1333                 quotedBool((pDexMethod->accessFlags & ACC_NATIVE) != 0));
   1334 
   1335             bool isSync =
   1336                 (pDexMethod->accessFlags & ACC_SYNCHRONIZED) != 0 ||
   1337                 (pDexMethod->accessFlags & ACC_DECLARED_SYNCHRONIZED) != 0;
   1338             printf(" synchronized=%s\n", quotedBool(isSync));
   1339         }
   1340 
   1341         printf(" static=%s\n",
   1342             quotedBool((pDexMethod->accessFlags & ACC_STATIC) != 0));
   1343         printf(" final=%s\n",
   1344             quotedBool((pDexMethod->accessFlags & ACC_FINAL) != 0));
   1345         // "deprecated=" not knowable w/o parsing annotations
   1346         printf(" visibility=%s\n",
   1347             quotedVisibility(pDexMethod->accessFlags));
   1348 
   1349         printf(">\n");
   1350 
   1351         /*
   1352          * Parameters.
   1353          */
   1354         if (typeDescriptor[0] != '(') {
   1355             fprintf(stderr, "ERROR: bad descriptor '%s'\n", typeDescriptor);
   1356             goto bail;
   1357         }
   1358 
   1359         char tmpBuf[strlen(typeDescriptor)+1];      /* more than big enough */
   1360         int argNum = 0;
   1361 
   1362         const char* base = typeDescriptor+1;
   1363 
   1364         while (*base != ')') {
   1365             char* cp = tmpBuf;
   1366 
   1367             while (*base == '[')
   1368                 *cp++ = *base++;
   1369 
   1370             if (*base == 'L') {
   1371                 /* copy through ';' */
   1372                 do {
   1373                     *cp = *base++;
   1374                 } while (*cp++ != ';');
   1375             } else {
   1376                 /* primitive char, copy it */
   1377                 if (strchr("ZBCSIFJD", *base) == NULL) {
   1378                     fprintf(stderr, "ERROR: bad method signature '%s'\n", base);
   1379                     goto bail;
   1380                 }
   1381                 *cp++ = *base++;
   1382             }
   1383 
   1384             /* null terminate and display */
   1385             *cp++ = '\0';
   1386 
   1387             char* tmp = descriptorToDot(tmpBuf);
   1388             printf("<parameter name=\"arg%d\" type=\"%s\">\n</parameter>\n",
   1389                 argNum++, tmp);
   1390             free(tmp);
   1391         }
   1392 
   1393         if (constructor)
   1394             printf("</constructor>\n");
   1395         else
   1396             printf("</method>\n");
   1397     }
   1398 
   1399 bail:
   1400     free(typeDescriptor);
   1401     free(accessStr);
   1402 }
   1403 
   1404 /*
   1405  * Dump a static (class) field.
   1406  */
   1407 void dumpSField(const DexFile* pDexFile, const DexField* pSField, int i)
   1408 {
   1409     const DexFieldId* pFieldId;
   1410     const char* backDescriptor;
   1411     const char* name;
   1412     const char* typeDescriptor;
   1413     char* accessStr;
   1414 
   1415     if (gOptions.exportsOnly &&
   1416         (pSField->accessFlags & (ACC_PUBLIC | ACC_PROTECTED)) == 0)
   1417     {
   1418         return;
   1419     }
   1420 
   1421     pFieldId = dexGetFieldId(pDexFile, pSField->fieldIdx);
   1422     name = dexStringById(pDexFile, pFieldId->nameIdx);
   1423     typeDescriptor = dexStringByTypeIdx(pDexFile, pFieldId->typeIdx);
   1424     backDescriptor = dexStringByTypeIdx(pDexFile, pFieldId->classIdx);
   1425 
   1426     accessStr = createAccessFlagStr(pSField->accessFlags, kAccessForField);
   1427 
   1428     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1429         printf("    #%d              : (in %s)\n", i, backDescriptor);
   1430         printf("      name          : '%s'\n", name);
   1431         printf("      type          : '%s'\n", typeDescriptor);
   1432         printf("      access        : 0x%04x (%s)\n",
   1433             pSField->accessFlags, accessStr);
   1434     } else if (gOptions.outputFormat == OUTPUT_XML) {
   1435         char* tmp;
   1436 
   1437         printf("<field name=\"%s\"\n", name);
   1438 
   1439         tmp = descriptorToDot(typeDescriptor);
   1440         printf(" type=\"%s\"\n", tmp);
   1441         free(tmp);
   1442 
   1443         printf(" transient=%s\n",
   1444             quotedBool((pSField->accessFlags & ACC_TRANSIENT) != 0));
   1445         printf(" volatile=%s\n",
   1446             quotedBool((pSField->accessFlags & ACC_VOLATILE) != 0));
   1447         // "value=" not knowable w/o parsing annotations
   1448         printf(" static=%s\n",
   1449             quotedBool((pSField->accessFlags & ACC_STATIC) != 0));
   1450         printf(" final=%s\n",
   1451             quotedBool((pSField->accessFlags & ACC_FINAL) != 0));
   1452         // "deprecated=" not knowable w/o parsing annotations
   1453         printf(" visibility=%s\n",
   1454             quotedVisibility(pSField->accessFlags));
   1455         printf(">\n</field>\n");
   1456     }
   1457 
   1458     free(accessStr);
   1459 }
   1460 
   1461 /*
   1462  * Dump an instance field.
   1463  */
   1464 void dumpIField(const DexFile* pDexFile, const DexField* pIField, int i)
   1465 {
   1466     dumpSField(pDexFile, pIField, i);
   1467 }
   1468 
   1469 /*
   1470  * Dump the class.
   1471  *
   1472  * Note "idx" is a DexClassDef index, not a DexTypeId index.
   1473  *
   1474  * If "*pLastPackage" is NULL or does not match the current class' package,
   1475  * the value will be replaced with a newly-allocated string.
   1476  */
   1477 void dumpClass(DexFile* pDexFile, int idx, char** pLastPackage)
   1478 {
   1479     const DexTypeList* pInterfaces;
   1480     const DexClassDef* pClassDef;
   1481     DexClassData* pClassData = NULL;
   1482     const u1* pEncodedData;
   1483     const char* fileName;
   1484     const char* classDescriptor;
   1485     const char* superclassDescriptor;
   1486     char* accessStr = NULL;
   1487     int i;
   1488 
   1489     pClassDef = dexGetClassDef(pDexFile, idx);
   1490 
   1491     if (gOptions.exportsOnly && (pClassDef->accessFlags & ACC_PUBLIC) == 0) {
   1492         //printf("<!-- omitting non-public class %s -->\n",
   1493         //    classDescriptor);
   1494         goto bail;
   1495     }
   1496 
   1497     pEncodedData = dexGetClassData(pDexFile, pClassDef);
   1498     pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
   1499 
   1500     if (pClassData == NULL) {
   1501         printf("Trouble reading class data (#%d)\n", idx);
   1502         goto bail;
   1503     }
   1504 
   1505     classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
   1506 
   1507     /*
   1508      * For the XML output, show the package name.  Ideally we'd gather
   1509      * up the classes, sort them, and dump them alphabetically so the
   1510      * package name wouldn't jump around, but that's not a great plan
   1511      * for something that needs to run on the device.
   1512      */
   1513     if (!(classDescriptor[0] == 'L' &&
   1514           classDescriptor[strlen(classDescriptor)-1] == ';'))
   1515     {
   1516         /* arrays and primitives should not be defined explicitly */
   1517         fprintf(stderr, "Malformed class name '%s'\n", classDescriptor);
   1518         /* keep going? */
   1519     } else if (gOptions.outputFormat == OUTPUT_XML) {
   1520         char* mangle;
   1521         char* lastSlash;
   1522         char* cp;
   1523 
   1524         mangle = strdup(classDescriptor + 1);
   1525         mangle[strlen(mangle)-1] = '\0';
   1526 
   1527         /* reduce to just the package name */
   1528         lastSlash = strrchr(mangle, '/');
   1529         if (lastSlash != NULL) {
   1530             *lastSlash = '\0';
   1531         } else {
   1532             *mangle = '\0';
   1533         }
   1534 
   1535         for (cp = mangle; *cp != '\0'; cp++) {
   1536             if (*cp == '/')
   1537                 *cp = '.';
   1538         }
   1539 
   1540         if (*pLastPackage == NULL || strcmp(mangle, *pLastPackage) != 0) {
   1541             /* start of a new package */
   1542             if (*pLastPackage != NULL)
   1543                 printf("</package>\n");
   1544             printf("<package name=\"%s\"\n>\n", mangle);
   1545             free(*pLastPackage);
   1546             *pLastPackage = mangle;
   1547         } else {
   1548             free(mangle);
   1549         }
   1550     }
   1551 
   1552     accessStr = createAccessFlagStr(pClassDef->accessFlags, kAccessForClass);
   1553 
   1554     if (pClassDef->superclassIdx == kDexNoIndex) {
   1555         superclassDescriptor = NULL;
   1556     } else {
   1557         superclassDescriptor =
   1558             dexStringByTypeIdx(pDexFile, pClassDef->superclassIdx);
   1559     }
   1560 
   1561     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1562         printf("Class #%d            -\n", idx);
   1563         printf("  Class descriptor  : '%s'\n", classDescriptor);
   1564         printf("  Access flags      : 0x%04x (%s)\n",
   1565             pClassDef->accessFlags, accessStr);
   1566 
   1567         if (superclassDescriptor != NULL)
   1568             printf("  Superclass        : '%s'\n", superclassDescriptor);
   1569 
   1570         printf("  Interfaces        -\n");
   1571     } else {
   1572         char* tmp;
   1573 
   1574         tmp = descriptorClassToDot(classDescriptor);
   1575         printf("<class name=\"%s\"\n", tmp);
   1576         free(tmp);
   1577 
   1578         if (superclassDescriptor != NULL) {
   1579             tmp = descriptorToDot(superclassDescriptor);
   1580             printf(" extends=\"%s\"\n", tmp);
   1581             free(tmp);
   1582         }
   1583         printf(" abstract=%s\n",
   1584             quotedBool((pClassDef->accessFlags & ACC_ABSTRACT) != 0));
   1585         printf(" static=%s\n",
   1586             quotedBool((pClassDef->accessFlags & ACC_STATIC) != 0));
   1587         printf(" final=%s\n",
   1588             quotedBool((pClassDef->accessFlags & ACC_FINAL) != 0));
   1589         // "deprecated=" not knowable w/o parsing annotations
   1590         printf(" visibility=%s\n",
   1591             quotedVisibility(pClassDef->accessFlags));
   1592         printf(">\n");
   1593     }
   1594     pInterfaces = dexGetInterfacesList(pDexFile, pClassDef);
   1595     if (pInterfaces != NULL) {
   1596         for (i = 0; i < (int) pInterfaces->size; i++)
   1597             dumpInterface(pDexFile, dexGetTypeItem(pInterfaces, i), i);
   1598     }
   1599 
   1600     if (gOptions.outputFormat == OUTPUT_PLAIN)
   1601         printf("  Static fields     -\n");
   1602     for (i = 0; i < (int) pClassData->header.staticFieldsSize; i++) {
   1603         dumpSField(pDexFile, &pClassData->staticFields[i], i);
   1604     }
   1605 
   1606     if (gOptions.outputFormat == OUTPUT_PLAIN)
   1607         printf("  Instance fields   -\n");
   1608     for (i = 0; i < (int) pClassData->header.instanceFieldsSize; i++) {
   1609         dumpIField(pDexFile, &pClassData->instanceFields[i], i);
   1610     }
   1611 
   1612     if (gOptions.outputFormat == OUTPUT_PLAIN)
   1613         printf("  Direct methods    -\n");
   1614     for (i = 0; i < (int) pClassData->header.directMethodsSize; i++) {
   1615         dumpMethod(pDexFile, &pClassData->directMethods[i], i);
   1616     }
   1617 
   1618     if (gOptions.outputFormat == OUTPUT_PLAIN)
   1619         printf("  Virtual methods   -\n");
   1620     for (i = 0; i < (int) pClassData->header.virtualMethodsSize; i++) {
   1621         dumpMethod(pDexFile, &pClassData->virtualMethods[i], i);
   1622     }
   1623 
   1624     // TODO: Annotations.
   1625 
   1626     if (pClassDef->sourceFileIdx != kDexNoIndex)
   1627         fileName = dexStringById(pDexFile, pClassDef->sourceFileIdx);
   1628     else
   1629         fileName = "unknown";
   1630 
   1631     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1632         printf("  source_file_idx   : %d (%s)\n",
   1633             pClassDef->sourceFileIdx, fileName);
   1634         printf("\n");
   1635     }
   1636 
   1637     if (gOptions.outputFormat == OUTPUT_XML) {
   1638         printf("</class>\n");
   1639     }
   1640 
   1641 bail:
   1642     free(pClassData);
   1643     free(accessStr);
   1644 }
   1645 
   1646 
   1647 /*
   1648  * Advance "ptr" to ensure 32-bit alignment.
   1649  */
   1650 static inline const u1* align32(const u1* ptr)
   1651 {
   1652     return (u1*) (((uintptr_t) ptr + 3) & ~0x03);
   1653 }
   1654 
   1655 
   1656 /*
   1657  * Dump a map in the "differential" format.
   1658  *
   1659  * TODO: show a hex dump of the compressed data.  (We can show the
   1660  * uncompressed data if we move the compression code to libdex; otherwise
   1661  * it's too complex to merit a fast & fragile implementation here.)
   1662  */
   1663 void dumpDifferentialCompressedMap(const u1** pData)
   1664 {
   1665     const u1* data = *pData;
   1666     const u1* dataStart = data -1;      // format byte already removed
   1667     u1 regWidth;
   1668     u2 numEntries;
   1669 
   1670     /* standard header */
   1671     regWidth = *data++;
   1672     numEntries = *data++;
   1673     numEntries |= (*data++) << 8;
   1674 
   1675     /* compressed data begins with the compressed data length */
   1676     int compressedLen = readUnsignedLeb128(&data);
   1677     int addrWidth = 1;
   1678     if ((*data & 0x80) != 0)
   1679         addrWidth++;
   1680 
   1681     int origLen = 4 + (addrWidth + regWidth) * numEntries;
   1682     int compLen = (data - dataStart) + compressedLen;
   1683 
   1684     printf("        (differential compression %d -> %d [%d -> %d])\n",
   1685         origLen, compLen,
   1686         (addrWidth + regWidth) * numEntries, compressedLen);
   1687 
   1688     /* skip past end of entry */
   1689     data += compressedLen;
   1690 
   1691     *pData = data;
   1692 }
   1693 
   1694 /*
   1695  * Dump register map contents of the current method.
   1696  *
   1697  * "*pData" should point to the start of the register map data.  Advances
   1698  * "*pData" to the start of the next map.
   1699  */
   1700 void dumpMethodMap(DexFile* pDexFile, const DexMethod* pDexMethod, int idx,
   1701     const u1** pData)
   1702 {
   1703     const u1* data = *pData;
   1704     const DexMethodId* pMethodId;
   1705     const char* name;
   1706     int offset = data - (u1*) pDexFile->pOptHeader;
   1707 
   1708     pMethodId = dexGetMethodId(pDexFile, pDexMethod->methodIdx);
   1709     name = dexStringById(pDexFile, pMethodId->nameIdx);
   1710     printf("      #%d: 0x%08x %s\n", idx, offset, name);
   1711 
   1712     u1 format;
   1713     int addrWidth;
   1714 
   1715     format = *data++;
   1716     if (format == 1) {              /* kRegMapFormatNone */
   1717         /* no map */
   1718         printf("        (no map)\n");
   1719         addrWidth = 0;
   1720     } else if (format == 2) {       /* kRegMapFormatCompact8 */
   1721         addrWidth = 1;
   1722     } else if (format == 3) {       /* kRegMapFormatCompact16 */
   1723         addrWidth = 2;
   1724     } else if (format == 4) {       /* kRegMapFormatDifferential */
   1725         dumpDifferentialCompressedMap(&data);
   1726         goto bail;
   1727     } else {
   1728         printf("        (unknown format %d!)\n", format);
   1729         /* don't know how to skip data; failure will cascade to end of class */
   1730         goto bail;
   1731     }
   1732 
   1733     if (addrWidth > 0) {
   1734         u1 regWidth;
   1735         u2 numEntries;
   1736         int idx, addr, byte;
   1737 
   1738         regWidth = *data++;
   1739         numEntries = *data++;
   1740         numEntries |= (*data++) << 8;
   1741 
   1742         for (idx = 0; idx < numEntries; idx++) {
   1743             addr = *data++;
   1744             if (addrWidth > 1)
   1745                 addr |= (*data++) << 8;
   1746 
   1747             printf("        %4x:", addr);
   1748             for (byte = 0; byte < regWidth; byte++) {
   1749                 printf(" %02x", *data++);
   1750             }
   1751             printf("\n");
   1752         }
   1753     }
   1754 
   1755 bail:
   1756     //if (addrWidth >= 0)
   1757     //    *pData = align32(data);
   1758     *pData = data;
   1759 }
   1760 
   1761 /*
   1762  * Dump the contents of the register map area.
   1763  *
   1764  * These are only present in optimized DEX files, and the structure is
   1765  * not really exposed to other parts of the VM itself.  We're going to
   1766  * dig through them here, but this is pretty fragile.  DO NOT rely on
   1767  * this or derive other code from it.
   1768  */
   1769 void dumpRegisterMaps(DexFile* pDexFile)
   1770 {
   1771     const u1* pClassPool = (const u1*)pDexFile->pRegisterMapPool;
   1772     const u4* classOffsets;
   1773     const u1* ptr;
   1774     u4 numClasses;
   1775     int baseFileOffset = (u1*) pClassPool - (u1*) pDexFile->pOptHeader;
   1776     int idx;
   1777 
   1778     if (pClassPool == NULL) {
   1779         printf("No register maps found\n");
   1780         return;
   1781     }
   1782 
   1783     ptr = pClassPool;
   1784     numClasses = get4LE(ptr);
   1785     ptr += sizeof(u4);
   1786     classOffsets = (const u4*) ptr;
   1787 
   1788     printf("RMAP begins at offset 0x%07x\n", baseFileOffset);
   1789     printf("Maps for %d classes\n", numClasses);
   1790     for (idx = 0; idx < (int) numClasses; idx++) {
   1791         const DexClassDef* pClassDef;
   1792         const char* classDescriptor;
   1793 
   1794         pClassDef = dexGetClassDef(pDexFile, idx);
   1795         classDescriptor = dexStringByTypeIdx(pDexFile, pClassDef->classIdx);
   1796 
   1797         printf("%4d: +%d (0x%08x) %s\n", idx, classOffsets[idx],
   1798             baseFileOffset + classOffsets[idx], classDescriptor);
   1799 
   1800         if (classOffsets[idx] == 0)
   1801             continue;
   1802 
   1803         /*
   1804          * What follows is a series of RegisterMap entries, one for every
   1805          * direct method, then one for every virtual method.
   1806          */
   1807         DexClassData* pClassData;
   1808         const u1* pEncodedData;
   1809         const u1* data = (u1*) pClassPool + classOffsets[idx];
   1810         u2 methodCount;
   1811         int i;
   1812 
   1813         pEncodedData = dexGetClassData(pDexFile, pClassDef);
   1814         pClassData = dexReadAndVerifyClassData(&pEncodedData, NULL);
   1815         if (pClassData == NULL) {
   1816             fprintf(stderr, "Trouble reading class data\n");
   1817             continue;
   1818         }
   1819 
   1820         methodCount = *data++;
   1821         methodCount |= (*data++) << 8;
   1822         data += 2;      /* two pad bytes follow methodCount */
   1823         if (methodCount != pClassData->header.directMethodsSize
   1824                             + pClassData->header.virtualMethodsSize)
   1825         {
   1826             printf("NOTE: method count discrepancy (%d != %d + %d)\n",
   1827                 methodCount, pClassData->header.directMethodsSize,
   1828                 pClassData->header.virtualMethodsSize);
   1829             /* this is bad, but keep going anyway */
   1830         }
   1831 
   1832         printf("    direct methods: %d\n",
   1833             pClassData->header.directMethodsSize);
   1834         for (i = 0; i < (int) pClassData->header.directMethodsSize; i++) {
   1835             dumpMethodMap(pDexFile, &pClassData->directMethods[i], i, &data);
   1836         }
   1837 
   1838         printf("    virtual methods: %d\n",
   1839             pClassData->header.virtualMethodsSize);
   1840         for (i = 0; i < (int) pClassData->header.virtualMethodsSize; i++) {
   1841             dumpMethodMap(pDexFile, &pClassData->virtualMethods[i], i, &data);
   1842         }
   1843 
   1844         free(pClassData);
   1845     }
   1846 }
   1847 
   1848 static const DexMapItem* findMapItem(const DexFile* pDexFile, u4 type)
   1849 {
   1850     const u4 offset = pDexFile->pHeader->mapOff;
   1851     const DexMapList* list = (const DexMapList*)(pDexFile->baseAddr + offset);
   1852     for (u4 i = 0; i < list->size; ++i) {
   1853         if (list->list[i].type == type) {
   1854             return &list->list[i];
   1855         }
   1856     }
   1857     return nullptr;
   1858 }
   1859 
   1860 static void dumpMethodHandles(DexFile* pDexFile)
   1861 {
   1862     const DexMapItem* item = findMapItem(pDexFile, kDexTypeMethodHandleItem);
   1863     if (item == nullptr) return;
   1864     const DexMethodHandleItem* method_handles =
   1865             (const DexMethodHandleItem*)(pDexFile->baseAddr + item->offset);
   1866     for (u4 i = 0; i < item->size; ++i) {
   1867         const DexMethodHandleItem& mh = method_handles[i];
   1868         bool is_invoke = false;
   1869         const char* type;
   1870         switch (mh.methodHandleType) {
   1871             case 0:
   1872                 type = "put-static";
   1873                 break;
   1874             case 1:
   1875                 type = "get-static";
   1876                 break;
   1877             case 2:
   1878                 type = "put-instance";
   1879                 break;
   1880             case 3:
   1881                 type = "get-instance";
   1882                 break;
   1883             case 4:
   1884                 type = "invoke-static";
   1885                 is_invoke = true;
   1886                 break;
   1887             case 5:
   1888                 type = "invoke-instance";
   1889                 is_invoke = true;
   1890                 break;
   1891             case 6:
   1892                 type = "invoke-constructor";
   1893                 is_invoke = true;
   1894                 break;
   1895         }
   1896 
   1897         FieldMethodInfo info;
   1898         memset(&info, 0, sizeof(info));
   1899         if (is_invoke) {
   1900             getMethodInfo(pDexFile, mh.fieldOrMethodIdx, &info);
   1901         } else {
   1902             getFieldInfo(pDexFile, mh.fieldOrMethodIdx, &info);
   1903         }
   1904 
   1905         if (gOptions.outputFormat == OUTPUT_XML) {
   1906             printf("<method_handle index index=\"%u\"\n", i);
   1907             printf(" type=\"%s\"\n", type);
   1908             printf(" target_class=\"%s\"\n", info.classDescriptor);
   1909             printf(" target_member=\"%s\"\n", info.name);
   1910             printf(" target_member_type=\"%s\"\n", info.signature);
   1911             printf("</method_handle>\n");
   1912         } else {
   1913             printf("Method Handle #%u:\n", i);
   1914             printf("  type        : %s\n", type);
   1915             printf("  target      : %s %s\n", info.classDescriptor, info.name);
   1916             printf("  target_type : %s\n", info.signature);
   1917         }
   1918     }
   1919 }
   1920 
   1921 /* Helper for dumpCallSites(), which reads a 1- to 8- byte signed
   1922  * little endian value. */
   1923 static u8 readSignedLittleEndian(const u1** pData, u4 size) {
   1924     const u1* data = *pData;
   1925     u8 result = 0;
   1926     u4 i;
   1927 
   1928     for (i = 0; i < size; i++) {
   1929         result = (result >> 8) | (((int64_t)*data++) << 56);
   1930     }
   1931 
   1932     result >>= (8 - size) * 8;
   1933     *pData = data;
   1934     return result;
   1935 }
   1936 
   1937 /* Helper for dumpCallSites(), which reads a 1- to 8- byte unsigned
   1938  * little endian value. */
   1939 static u8 readUnsignedLittleEndian(const u1** pData, u4 size, bool fillOnRight = false) {
   1940     const u1* data = *pData;
   1941     u8 result = 0;
   1942     u4 i;
   1943 
   1944     for (i = 0; i < size; i++) {
   1945         result = (result >> 8) | (((u8)*data++) << 56);
   1946     }
   1947 
   1948     u8 oldResult = result;
   1949     if (!fillOnRight) {
   1950         result >>= (8u - size) * 8;
   1951     }
   1952 
   1953     *pData = data;
   1954     return result;
   1955 }
   1956 
   1957 static void dumpCallSites(DexFile* pDexFile)
   1958 {
   1959     const DexMapItem* item = findMapItem(pDexFile, kDexTypeCallSiteIdItem);
   1960     if (item == nullptr) return;
   1961     const DexCallSiteId* ids = (const DexCallSiteId*)(pDexFile->baseAddr + item->offset);
   1962     for (u4 index = 0; index < item->size; ++index) {
   1963         bool doXml = (gOptions.outputFormat == OUTPUT_XML);
   1964         printf(doXml ? "<call_site index=\"%u\">\n" : "Call Site #%u\n", index);
   1965         const u1* data = pDexFile->baseAddr + ids[index].callSiteOff;
   1966         u4 count = readUnsignedLeb128(&data);
   1967         for (u4 i = 0; i < count; ++i) {
   1968             printf(doXml ? "<link_argument index=\"%u\" " : "  link_argument[%u] : ", i);
   1969             u1 headerByte = *data++;
   1970             u4 valueType = headerByte & kDexAnnotationValueTypeMask;
   1971             u4 valueArg = headerByte >> kDexAnnotationValueArgShift;
   1972             switch (valueType) {
   1973                 case kDexAnnotationByte: {
   1974                     printf(doXml ? "type=\"byte\" value=\"%d\"/>" : "%d (byte)", (int)*data++);
   1975                     break;
   1976                 }
   1977                 case kDexAnnotationShort: {
   1978                     printf(doXml ? "type=\"short\" value=\"%d\"/>" : "%d (short)",
   1979                            (int) readSignedLittleEndian(&data, valueArg + 1));
   1980                     break;
   1981                 }
   1982                 case kDexAnnotationChar: {
   1983                     printf(doXml ? "type=\"short\" value=\"%u\"/>" : "%u (char)",
   1984                            (u2) readUnsignedLittleEndian(&data, valueArg + 1));
   1985                     break;
   1986                 }
   1987                 case kDexAnnotationInt: {
   1988                     printf(doXml ? "type=\"int\" value=\"%d\"/>" : "%d (int)",
   1989                            (int) readSignedLittleEndian(&data, valueArg + 1));
   1990                     break;
   1991                 }
   1992                 case kDexAnnotationLong: {
   1993                     printf(doXml ? "type=\"long\" value=\"%" PRId64 "\"/>" : "%" PRId64 " (long)",
   1994                            (int64_t) readSignedLittleEndian(&data, valueArg + 1));
   1995                     break;
   1996                 }
   1997                 case kDexAnnotationFloat: {
   1998                     u4 rawValue = (u4) (readUnsignedLittleEndian(&data, valueArg + 1, true) >> 32);
   1999                     printf(doXml ? "type=\"float\" value=\"%g\"/>" : "%g (float)",
   2000                            *((float*) &rawValue));
   2001                     break;
   2002                 }
   2003                 case kDexAnnotationDouble: {
   2004                     u8 rawValue = readUnsignedLittleEndian(&data, valueArg + 1, true);
   2005                     printf(doXml ? "type=\"double\" value=\"%g\"/>" : "%g (double)",
   2006                            *((double*) &rawValue));
   2007                     break;
   2008                 }
   2009                 case kDexAnnotationMethodType: {
   2010                     u4 idx = (u4) readUnsignedLittleEndian(&data, valueArg + 1);
   2011                     ProtoInfo protoInfo;
   2012                     memset(&protoInfo, 0, sizeof(protoInfo));
   2013                     getProtoInfo(pDexFile, idx, &protoInfo);
   2014                     printf(doXml ? "type=\"MethodType\" value=\"(%s)%s\"/>" : "(%s)%s (MethodType)",
   2015                            protoInfo.parameterTypes, protoInfo.returnType);
   2016                     free(protoInfo.parameterTypes);
   2017                     break;
   2018                 }
   2019                 case kDexAnnotationMethodHandle: {
   2020                     u4 idx = (u4) readUnsignedLittleEndian(&data, valueArg + 1);
   2021                     printf(doXml ? "type=\"MethodHandle\" value=\"%u\"/>" : "%u (MethodHandle)",
   2022                            idx);
   2023                     break;
   2024                 }
   2025                 case kDexAnnotationString: {
   2026                     u4 idx = (u4) readUnsignedLittleEndian(&data, valueArg + 1);
   2027                     printf(doXml ? "type=\"String\" value=\"%s\"/>" : "%s (String)",
   2028                            dexStringById(pDexFile, idx));
   2029                     break;
   2030                 }
   2031                 case kDexAnnotationType: {
   2032                     u4 idx = (u4) readUnsignedLittleEndian(&data, valueArg + 1);
   2033                     printf(doXml ? "type=\"Class\" value=\"%s\"/>" : "%s (Class)",
   2034                            dexStringByTypeIdx(pDexFile, idx));
   2035                     break;
   2036                 }
   2037                 case kDexAnnotationNull: {
   2038                     printf(doXml ? "type=\"null\" value=\"null\"/>" : "null (null)");
   2039                     break;
   2040                 }
   2041                 case kDexAnnotationBoolean: {
   2042                     printf(doXml ? "type=\"boolean\" value=\"%s\"/>" : "%s (boolean)",
   2043                            (valueArg & 1) == 0 ? "false" : "true");
   2044                     break;
   2045                 }
   2046                 default:
   2047                     // Other types are not anticipated being reached here.
   2048                     printf("Unexpected type found, bailing on call site info.\n");
   2049                     i = count;
   2050                     break;
   2051             }
   2052             printf("\n");
   2053         }
   2054 
   2055         if (doXml) {
   2056             printf("</callsite>\n");
   2057         }
   2058     }
   2059 }
   2060 
   2061 /*
   2062  * Dump the requested sections of the file.
   2063  */
   2064 void processDexFile(const char* fileName, DexFile* pDexFile)
   2065 {
   2066     char* package = NULL;
   2067     int i;
   2068 
   2069     if (gOptions.verbose) {
   2070         printf("Opened '%s', DEX version '%.3s'\n", fileName,
   2071             pDexFile->pHeader->magic +4);
   2072     }
   2073 
   2074     if (gOptions.dumpRegisterMaps) {
   2075         dumpRegisterMaps(pDexFile);
   2076         return;
   2077     }
   2078 
   2079     if (gOptions.showFileHeaders) {
   2080         dumpFileHeader(pDexFile);
   2081         dumpOptDirectory(pDexFile);
   2082     }
   2083 
   2084     if (gOptions.outputFormat == OUTPUT_XML)
   2085         printf("<api>\n");
   2086 
   2087     for (i = 0; i < (int) pDexFile->pHeader->classDefsSize; i++) {
   2088         if (gOptions.showSectionHeaders)
   2089             dumpClassDef(pDexFile, i);
   2090 
   2091         dumpClass(pDexFile, i, &package);
   2092     }
   2093 
   2094     dumpMethodHandles(pDexFile);
   2095     dumpCallSites(pDexFile);
   2096 
   2097     /* free the last one allocated */
   2098     if (package != NULL) {
   2099         printf("</package>\n");
   2100         free(package);
   2101     }
   2102 
   2103     if (gOptions.outputFormat == OUTPUT_XML)
   2104         printf("</api>\n");
   2105 }
   2106 
   2107 
   2108 /*
   2109  * Process one file.
   2110  */
   2111 int process(const char* fileName)
   2112 {
   2113     DexFile* pDexFile = NULL;
   2114     MemMapping map;
   2115     bool mapped = false;
   2116     int result = -1;
   2117 
   2118     if (gOptions.verbose)
   2119         printf("Processing '%s'...\n", fileName);
   2120 
   2121     if (dexOpenAndMap(fileName, gOptions.tempFileName, &map, false) != 0) {
   2122         return result;
   2123     }
   2124     mapped = true;
   2125 
   2126     int flags = kDexParseVerifyChecksum;
   2127     if (gOptions.ignoreBadChecksum)
   2128         flags |= kDexParseContinueOnError;
   2129 
   2130     pDexFile = dexFileParse((u1*)map.addr, map.length, flags);
   2131     if (pDexFile == NULL) {
   2132         fprintf(stderr, "ERROR: DEX parse failed\n");
   2133         goto bail;
   2134     }
   2135 
   2136     if (gOptions.checksumOnly) {
   2137         printf("Checksum verified\n");
   2138     } else {
   2139         processDexFile(fileName, pDexFile);
   2140     }
   2141 
   2142     result = 0;
   2143 
   2144 bail:
   2145     if (mapped)
   2146         sysReleaseShmem(&map);
   2147     if (pDexFile != NULL)
   2148         dexFileFree(pDexFile);
   2149     return result;
   2150 }
   2151 
   2152 
   2153 /*
   2154  * Show usage.
   2155  */
   2156 void usage(void)
   2157 {
   2158     fprintf(stderr, "Copyright (C) 2007 The Android Open Source Project\n\n");
   2159     fprintf(stderr,
   2160         "%s: [-c] [-d] [-f] [-h] [-i] [-l layout] [-m] [-t tempfile] dexfile...\n",
   2161         gProgName);
   2162     fprintf(stderr, "\n");
   2163     fprintf(stderr, " -c : verify checksum and exit\n");
   2164     fprintf(stderr, " -d : disassemble code sections\n");
   2165     fprintf(stderr, " -f : display summary information from file header\n");
   2166     fprintf(stderr, " -h : display file header details\n");
   2167     fprintf(stderr, " -i : ignore checksum failures\n");
   2168     fprintf(stderr, " -l : output layout, either 'plain' or 'xml'\n");
   2169     fprintf(stderr, " -m : dump register maps (and nothing else)\n");
   2170     fprintf(stderr, " -t : temp file name (defaults to /sdcard/dex-temp-*)\n");
   2171 }
   2172 
   2173 /*
   2174  * Parse args.
   2175  *
   2176  * I'm not using getopt_long() because we may not have it in libc.
   2177  */
   2178 int main(int argc, char* const argv[])
   2179 {
   2180     bool wantUsage = false;
   2181     int ic;
   2182 
   2183     memset(&gOptions, 0, sizeof(gOptions));
   2184     gOptions.verbose = true;
   2185 
   2186     while (1) {
   2187         ic = getopt(argc, argv, "cdfhil:mt:");
   2188         if (ic < 0)
   2189             break;
   2190 
   2191         switch (ic) {
   2192         case 'c':       // verify the checksum then exit
   2193             gOptions.checksumOnly = true;
   2194             break;
   2195         case 'd':       // disassemble Dalvik instructions
   2196             gOptions.disassemble = true;
   2197             break;
   2198         case 'f':       // dump outer file header
   2199             gOptions.showFileHeaders = true;
   2200             break;
   2201         case 'h':       // dump section headers, i.e. all meta-data
   2202             gOptions.showSectionHeaders = true;
   2203             break;
   2204         case 'i':       // continue even if checksum is bad
   2205             gOptions.ignoreBadChecksum = true;
   2206             break;
   2207         case 'l':       // layout
   2208             if (strcmp(optarg, "plain") == 0) {
   2209                 gOptions.outputFormat = OUTPUT_PLAIN;
   2210             } else if (strcmp(optarg, "xml") == 0) {
   2211                 gOptions.outputFormat = OUTPUT_XML;
   2212                 gOptions.verbose = false;
   2213                 gOptions.exportsOnly = true;
   2214             } else {
   2215                 wantUsage = true;
   2216             }
   2217             break;
   2218         case 'm':       // dump register maps only
   2219             gOptions.dumpRegisterMaps = true;
   2220             break;
   2221         case 't':       // temp file, used when opening compressed Jar
   2222             gOptions.tempFileName = optarg;
   2223             break;
   2224         default:
   2225             wantUsage = true;
   2226             break;
   2227         }
   2228     }
   2229 
   2230     if (optind == argc) {
   2231         fprintf(stderr, "%s: no file specified\n", gProgName);
   2232         wantUsage = true;
   2233     }
   2234 
   2235     if (gOptions.checksumOnly && gOptions.ignoreBadChecksum) {
   2236         fprintf(stderr, "Can't specify both -c and -i\n");
   2237         wantUsage = true;
   2238     }
   2239 
   2240     if (wantUsage) {
   2241         usage();
   2242         return 2;
   2243     }
   2244 
   2245     int result = 0;
   2246     while (optind < argc) {
   2247         result |= process(argv[optind++]);
   2248     }
   2249 
   2250     return (result != 0);
   2251 }
   2252