Home | History | Annotate | Download | only in dexdump
      1 /*
      2  * Copyright (C) 2015 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  * Implementation file of the dexdump utility.
     17  *
     18  * This is a re-implementation of the original dexdump utility that was
     19  * based on Dalvik functions in libdex into a new dexdump that is now
     20  * based on Art functions in libart instead. The output is very similar to
     21  * to the original for correct DEX files. Error messages may differ, however.
     22  * Also, ODEX files are no longer supported.
     23  *
     24  * The dexdump tool is intended to mimic objdump.  When possible, use
     25  * similar command-line arguments.
     26  *
     27  * Differences between XML output and the "current.xml" file:
     28  * - classes in same package are not all grouped together; nothing is sorted
     29  * - no "deprecated" on fields and methods
     30  * - no parameter names
     31  * - no generic signatures on parameters, e.g. type="java.lang.Class<?>"
     32  * - class shows declared fields and methods; does not show inherited fields
     33  */
     34 
     35 #include "dexdump.h"
     36 
     37 #include <inttypes.h>
     38 #include <stdio.h>
     39 
     40 #include <memory>
     41 #include <sstream>
     42 #include <vector>
     43 
     44 #include "android-base/file.h"
     45 #include "android-base/logging.h"
     46 #include "android-base/stringprintf.h"
     47 
     48 #include "dex/code_item_accessors-inl.h"
     49 #include "dex/dex_file-inl.h"
     50 #include "dex/dex_file_exception_helpers.h"
     51 #include "dex/dex_file_loader.h"
     52 #include "dex/dex_file_types.h"
     53 #include "dex/dex_instruction-inl.h"
     54 #include "dexdump_cfg.h"
     55 
     56 namespace art {
     57 
     58 /*
     59  * Options parsed in main driver.
     60  */
     61 struct Options gOptions;
     62 
     63 /*
     64  * Output file. Defaults to stdout.
     65  */
     66 FILE* gOutFile = stdout;
     67 
     68 /*
     69  * Data types that match the definitions in the VM specification.
     70  */
     71 typedef uint8_t  u1;
     72 typedef uint16_t u2;
     73 typedef uint32_t u4;
     74 typedef uint64_t u8;
     75 typedef int8_t   s1;
     76 typedef int16_t  s2;
     77 typedef int32_t  s4;
     78 typedef int64_t  s8;
     79 
     80 /*
     81  * Basic information about a field or a method.
     82  */
     83 struct FieldMethodInfo {
     84   const char* classDescriptor;
     85   const char* name;
     86   const char* signature;
     87 };
     88 
     89 /*
     90  * Flags for use with createAccessFlagStr().
     91  */
     92 enum AccessFor {
     93   kAccessForClass = 0, kAccessForMethod = 1, kAccessForField = 2, kAccessForMAX
     94 };
     95 const int kNumFlags = 18;
     96 
     97 /*
     98  * Gets 2 little-endian bytes.
     99  */
    100 static inline u2 get2LE(unsigned char const* pSrc) {
    101   return pSrc[0] | (pSrc[1] << 8);
    102 }
    103 
    104 /*
    105  * Converts a single-character primitive type into human-readable form.
    106  */
    107 static const char* primitiveTypeLabel(char typeChar) {
    108   switch (typeChar) {
    109     case 'B': return "byte";
    110     case 'C': return "char";
    111     case 'D': return "double";
    112     case 'F': return "float";
    113     case 'I': return "int";
    114     case 'J': return "long";
    115     case 'S': return "short";
    116     case 'V': return "void";
    117     case 'Z': return "boolean";
    118     default:  return "UNKNOWN";
    119   }  // switch
    120 }
    121 
    122 /*
    123  * Converts a type descriptor to human-readable "dotted" form.  For
    124  * example, "Ljava/lang/String;" becomes "java.lang.String", and
    125  * "[I" becomes "int[]".  Also converts '$' to '.', which means this
    126  * form can't be converted back to a descriptor.
    127  */
    128 static std::unique_ptr<char[]> descriptorToDot(const char* str) {
    129   int targetLen = strlen(str);
    130   int offset = 0;
    131 
    132   // Strip leading [s; will be added to end.
    133   while (targetLen > 1 && str[offset] == '[') {
    134     offset++;
    135     targetLen--;
    136   }  // while
    137 
    138   const int arrayDepth = offset;
    139 
    140   if (targetLen == 1) {
    141     // Primitive type.
    142     str = primitiveTypeLabel(str[offset]);
    143     offset = 0;
    144     targetLen = strlen(str);
    145   } else {
    146     // Account for leading 'L' and trailing ';'.
    147     if (targetLen >= 2 && str[offset] == 'L' &&
    148         str[offset + targetLen - 1] == ';') {
    149       targetLen -= 2;
    150       offset++;
    151     }
    152   }
    153 
    154   // Copy class name over.
    155   std::unique_ptr<char[]> newStr(new char[targetLen + arrayDepth * 2 + 1]);
    156   int i = 0;
    157   for (; i < targetLen; i++) {
    158     const char ch = str[offset + i];
    159     newStr[i] = (ch == '/' || ch == '$') ? '.' : ch;
    160   }  // for
    161 
    162   // Add the appropriate number of brackets for arrays.
    163   for (int j = 0; j < arrayDepth; j++) {
    164     newStr[i++] = '[';
    165     newStr[i++] = ']';
    166   }  // for
    167 
    168   newStr[i] = '\0';
    169   return newStr;
    170 }
    171 
    172 /*
    173  * Converts the class name portion of a type descriptor to human-readable
    174  * "dotted" form. For example, "Ljava/lang/String;" becomes "String".
    175  */
    176 static std::unique_ptr<char[]> descriptorClassToDot(const char* str) {
    177   // Reduce to just the class name prefix.
    178   const char* lastSlash = strrchr(str, '/');
    179   if (lastSlash == nullptr) {
    180     lastSlash = str + 1;  // start past 'L'
    181   } else {
    182     lastSlash++;          // start past '/'
    183   }
    184 
    185   // Copy class name over, trimming trailing ';'.
    186   const int targetLen = strlen(lastSlash);
    187   std::unique_ptr<char[]> newStr(new char[targetLen]);
    188   for (int i = 0; i < targetLen - 1; i++) {
    189     const char ch = lastSlash[i];
    190     newStr[i] = ch == '$' ? '.' : ch;
    191   }  // for
    192   newStr[targetLen - 1] = '\0';
    193   return newStr;
    194 }
    195 
    196 /*
    197  * Returns string representing the boolean value.
    198  */
    199 static const char* strBool(bool val) {
    200   return val ? "true" : "false";
    201 }
    202 
    203 /*
    204  * Returns a quoted string representing the boolean value.
    205  */
    206 static const char* quotedBool(bool val) {
    207   return val ? "\"true\"" : "\"false\"";
    208 }
    209 
    210 /*
    211  * Returns a quoted string representing the access flags.
    212  */
    213 static const char* quotedVisibility(u4 accessFlags) {
    214   if (accessFlags & kAccPublic) {
    215     return "\"public\"";
    216   } else if (accessFlags & kAccProtected) {
    217     return "\"protected\"";
    218   } else if (accessFlags & kAccPrivate) {
    219     return "\"private\"";
    220   } else {
    221     return "\"package\"";
    222   }
    223 }
    224 
    225 /*
    226  * Counts the number of '1' bits in a word.
    227  */
    228 static int countOnes(u4 val) {
    229   val = val - ((val >> 1) & 0x55555555);
    230   val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
    231   return (((val + (val >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
    232 }
    233 
    234 /*
    235  * Creates a new string with human-readable access flags.
    236  *
    237  * In the base language the access_flags fields are type u2; in Dalvik
    238  * they're u4.
    239  */
    240 static char* createAccessFlagStr(u4 flags, AccessFor forWhat) {
    241   static const char* kAccessStrings[kAccessForMAX][kNumFlags] = {
    242     {
    243       "PUBLIC",                /* 0x00001 */
    244       "PRIVATE",               /* 0x00002 */
    245       "PROTECTED",             /* 0x00004 */
    246       "STATIC",                /* 0x00008 */
    247       "FINAL",                 /* 0x00010 */
    248       "?",                     /* 0x00020 */
    249       "?",                     /* 0x00040 */
    250       "?",                     /* 0x00080 */
    251       "?",                     /* 0x00100 */
    252       "INTERFACE",             /* 0x00200 */
    253       "ABSTRACT",              /* 0x00400 */
    254       "?",                     /* 0x00800 */
    255       "SYNTHETIC",             /* 0x01000 */
    256       "ANNOTATION",            /* 0x02000 */
    257       "ENUM",                  /* 0x04000 */
    258       "?",                     /* 0x08000 */
    259       "VERIFIED",              /* 0x10000 */
    260       "OPTIMIZED",             /* 0x20000 */
    261     }, {
    262       "PUBLIC",                /* 0x00001 */
    263       "PRIVATE",               /* 0x00002 */
    264       "PROTECTED",             /* 0x00004 */
    265       "STATIC",                /* 0x00008 */
    266       "FINAL",                 /* 0x00010 */
    267       "SYNCHRONIZED",          /* 0x00020 */
    268       "BRIDGE",                /* 0x00040 */
    269       "VARARGS",               /* 0x00080 */
    270       "NATIVE",                /* 0x00100 */
    271       "?",                     /* 0x00200 */
    272       "ABSTRACT",              /* 0x00400 */
    273       "STRICT",                /* 0x00800 */
    274       "SYNTHETIC",             /* 0x01000 */
    275       "?",                     /* 0x02000 */
    276       "?",                     /* 0x04000 */
    277       "MIRANDA",               /* 0x08000 */
    278       "CONSTRUCTOR",           /* 0x10000 */
    279       "DECLARED_SYNCHRONIZED", /* 0x20000 */
    280     }, {
    281       "PUBLIC",                /* 0x00001 */
    282       "PRIVATE",               /* 0x00002 */
    283       "PROTECTED",             /* 0x00004 */
    284       "STATIC",                /* 0x00008 */
    285       "FINAL",                 /* 0x00010 */
    286       "?",                     /* 0x00020 */
    287       "VOLATILE",              /* 0x00040 */
    288       "TRANSIENT",             /* 0x00080 */
    289       "?",                     /* 0x00100 */
    290       "?",                     /* 0x00200 */
    291       "?",                     /* 0x00400 */
    292       "?",                     /* 0x00800 */
    293       "SYNTHETIC",             /* 0x01000 */
    294       "?",                     /* 0x02000 */
    295       "ENUM",                  /* 0x04000 */
    296       "?",                     /* 0x08000 */
    297       "?",                     /* 0x10000 */
    298       "?",                     /* 0x20000 */
    299     },
    300   };
    301 
    302   // Allocate enough storage to hold the expected number of strings,
    303   // plus a space between each.  We over-allocate, using the longest
    304   // string above as the base metric.
    305   const int kLongest = 21;  // The strlen of longest string above.
    306   const int count = countOnes(flags);
    307   char* str;
    308   char* cp;
    309   cp = str = reinterpret_cast<char*>(malloc(count * (kLongest + 1) + 1));
    310 
    311   for (int i = 0; i < kNumFlags; i++) {
    312     if (flags & 0x01) {
    313       const char* accessStr = kAccessStrings[forWhat][i];
    314       const int len = strlen(accessStr);
    315       if (cp != str) {
    316         *cp++ = ' ';
    317       }
    318       memcpy(cp, accessStr, len);
    319       cp += len;
    320     }
    321     flags >>= 1;
    322   }  // for
    323 
    324   *cp = '\0';
    325   return str;
    326 }
    327 
    328 /*
    329  * Copies character data from "data" to "out", converting non-ASCII values
    330  * to fprintf format chars or an ASCII filler ('.' or '?').
    331  *
    332  * The output buffer must be able to hold (2*len)+1 bytes.  The result is
    333  * NULL-terminated.
    334  */
    335 static void asciify(char* out, const unsigned char* data, size_t len) {
    336   while (len--) {
    337     if (*data < 0x20) {
    338       // Could do more here, but we don't need them yet.
    339       switch (*data) {
    340         case '\0':
    341           *out++ = '\\';
    342           *out++ = '0';
    343           break;
    344         case '\n':
    345           *out++ = '\\';
    346           *out++ = 'n';
    347           break;
    348         default:
    349           *out++ = '.';
    350           break;
    351       }  // switch
    352     } else if (*data >= 0x80) {
    353       *out++ = '?';
    354     } else {
    355       *out++ = *data;
    356     }
    357     data++;
    358   }  // while
    359   *out = '\0';
    360 }
    361 
    362 /*
    363  * Dumps a string value with some escape characters.
    364  */
    365 static void dumpEscapedString(const char* p) {
    366   fputs("\"", gOutFile);
    367   for (; *p; p++) {
    368     switch (*p) {
    369       case '\\':
    370         fputs("\\\\", gOutFile);
    371         break;
    372       case '\"':
    373         fputs("\\\"", gOutFile);
    374         break;
    375       case '\t':
    376         fputs("\\t", gOutFile);
    377         break;
    378       case '\n':
    379         fputs("\\n", gOutFile);
    380         break;
    381       case '\r':
    382         fputs("\\r", gOutFile);
    383         break;
    384       default:
    385         putc(*p, gOutFile);
    386     }  // switch
    387   }  // for
    388   fputs("\"", gOutFile);
    389 }
    390 
    391 /*
    392  * Dumps a string as an XML attribute value.
    393  */
    394 static void dumpXmlAttribute(const char* p) {
    395   for (; *p; p++) {
    396     switch (*p) {
    397       case '&':
    398         fputs("&amp;", gOutFile);
    399         break;
    400       case '<':
    401         fputs("&lt;", gOutFile);
    402         break;
    403       case '>':
    404         fputs("&gt;", gOutFile);
    405         break;
    406       case '"':
    407         fputs("&quot;", gOutFile);
    408         break;
    409       case '\t':
    410         fputs("&#x9;", gOutFile);
    411         break;
    412       case '\n':
    413         fputs("&#xA;", gOutFile);
    414         break;
    415       case '\r':
    416         fputs("&#xD;", gOutFile);
    417         break;
    418       default:
    419         putc(*p, gOutFile);
    420     }  // switch
    421   }  // for
    422 }
    423 
    424 /*
    425  * Reads variable width value, possibly sign extended at the last defined byte.
    426  */
    427 static u8 readVarWidth(const u1** data, u1 arg, bool sign_extend) {
    428   u8 value = 0;
    429   for (u4 i = 0; i <= arg; i++) {
    430     value |= static_cast<u8>(*(*data)++) << (i * 8);
    431   }
    432   if (sign_extend) {
    433     int shift = (7 - arg) * 8;
    434     return (static_cast<s8>(value) << shift) >> shift;
    435   }
    436   return value;
    437 }
    438 
    439 /*
    440  * Dumps encoded value.
    441  */
    442 static void dumpEncodedValue(const DexFile* pDexFile, const u1** data);  // forward
    443 static void dumpEncodedValue(const DexFile* pDexFile, const u1** data, u1 type, u1 arg) {
    444   switch (type) {
    445     case DexFile::kDexAnnotationByte:
    446       fprintf(gOutFile, "%" PRId8, static_cast<s1>(readVarWidth(data, arg, false)));
    447       break;
    448     case DexFile::kDexAnnotationShort:
    449       fprintf(gOutFile, "%" PRId16, static_cast<s2>(readVarWidth(data, arg, true)));
    450       break;
    451     case DexFile::kDexAnnotationChar:
    452       fprintf(gOutFile, "%" PRIu16, static_cast<u2>(readVarWidth(data, arg, false)));
    453       break;
    454     case DexFile::kDexAnnotationInt:
    455       fprintf(gOutFile, "%" PRId32, static_cast<s4>(readVarWidth(data, arg, true)));
    456       break;
    457     case DexFile::kDexAnnotationLong:
    458       fprintf(gOutFile, "%" PRId64, static_cast<s8>(readVarWidth(data, arg, true)));
    459       break;
    460     case DexFile::kDexAnnotationFloat: {
    461       // Fill on right.
    462       union {
    463         float f;
    464         u4 data;
    465       } conv;
    466       conv.data = static_cast<u4>(readVarWidth(data, arg, false)) << (3 - arg) * 8;
    467       fprintf(gOutFile, "%g", conv.f);
    468       break;
    469     }
    470     case DexFile::kDexAnnotationDouble: {
    471       // Fill on right.
    472       union {
    473         double d;
    474         u8 data;
    475       } conv;
    476       conv.data = readVarWidth(data, arg, false) << (7 - arg) * 8;
    477       fprintf(gOutFile, "%g", conv.d);
    478       break;
    479     }
    480     case DexFile::kDexAnnotationString: {
    481       const u4 idx = static_cast<u4>(readVarWidth(data, arg, false));
    482       if (gOptions.outputFormat == OUTPUT_PLAIN) {
    483         dumpEscapedString(pDexFile->StringDataByIdx(dex::StringIndex(idx)));
    484       } else {
    485         dumpXmlAttribute(pDexFile->StringDataByIdx(dex::StringIndex(idx)));
    486       }
    487       break;
    488     }
    489     case DexFile::kDexAnnotationType: {
    490       const u4 str_idx = static_cast<u4>(readVarWidth(data, arg, false));
    491       fputs(pDexFile->StringByTypeIdx(dex::TypeIndex(str_idx)), gOutFile);
    492       break;
    493     }
    494     case DexFile::kDexAnnotationField:
    495     case DexFile::kDexAnnotationEnum: {
    496       const u4 field_idx = static_cast<u4>(readVarWidth(data, arg, false));
    497       const DexFile::FieldId& pFieldId = pDexFile->GetFieldId(field_idx);
    498       fputs(pDexFile->StringDataByIdx(pFieldId.name_idx_), gOutFile);
    499       break;
    500     }
    501     case DexFile::kDexAnnotationMethod: {
    502       const u4 method_idx = static_cast<u4>(readVarWidth(data, arg, false));
    503       const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(method_idx);
    504       fputs(pDexFile->StringDataByIdx(pMethodId.name_idx_), gOutFile);
    505       break;
    506     }
    507     case DexFile::kDexAnnotationArray: {
    508       fputc('{', gOutFile);
    509       // Decode and display all elements.
    510       const u4 size = DecodeUnsignedLeb128(data);
    511       for (u4 i = 0; i < size; i++) {
    512         fputc(' ', gOutFile);
    513         dumpEncodedValue(pDexFile, data);
    514       }
    515       fputs(" }", gOutFile);
    516       break;
    517     }
    518     case DexFile::kDexAnnotationAnnotation: {
    519       const u4 type_idx = DecodeUnsignedLeb128(data);
    520       fputs(pDexFile->StringByTypeIdx(dex::TypeIndex(type_idx)), gOutFile);
    521       // Decode and display all name=value pairs.
    522       const u4 size = DecodeUnsignedLeb128(data);
    523       for (u4 i = 0; i < size; i++) {
    524         const u4 name_idx = DecodeUnsignedLeb128(data);
    525         fputc(' ', gOutFile);
    526         fputs(pDexFile->StringDataByIdx(dex::StringIndex(name_idx)), gOutFile);
    527         fputc('=', gOutFile);
    528         dumpEncodedValue(pDexFile, data);
    529       }
    530       break;
    531     }
    532     case DexFile::kDexAnnotationNull:
    533       fputs("null", gOutFile);
    534       break;
    535     case DexFile::kDexAnnotationBoolean:
    536       fputs(strBool(arg), gOutFile);
    537       break;
    538     default:
    539       fputs("????", gOutFile);
    540       break;
    541   }  // switch
    542 }
    543 
    544 /*
    545  * Dumps encoded value with prefix.
    546  */
    547 static void dumpEncodedValue(const DexFile* pDexFile, const u1** data) {
    548   const u1 enc = *(*data)++;
    549   dumpEncodedValue(pDexFile, data, enc & 0x1f, enc >> 5);
    550 }
    551 
    552 /*
    553  * Dumps the file header.
    554  */
    555 static void dumpFileHeader(const DexFile* pDexFile) {
    556   const DexFile::Header& pHeader = pDexFile->GetHeader();
    557   char sanitized[sizeof(pHeader.magic_) * 2 + 1];
    558   fprintf(gOutFile, "DEX file header:\n");
    559   asciify(sanitized, pHeader.magic_, sizeof(pHeader.magic_));
    560   fprintf(gOutFile, "magic               : '%s'\n", sanitized);
    561   fprintf(gOutFile, "checksum            : %08x\n", pHeader.checksum_);
    562   fprintf(gOutFile, "signature           : %02x%02x...%02x%02x\n",
    563           pHeader.signature_[0], pHeader.signature_[1],
    564           pHeader.signature_[DexFile::kSha1DigestSize - 2],
    565           pHeader.signature_[DexFile::kSha1DigestSize - 1]);
    566   fprintf(gOutFile, "file_size           : %d\n", pHeader.file_size_);
    567   fprintf(gOutFile, "header_size         : %d\n", pHeader.header_size_);
    568   fprintf(gOutFile, "link_size           : %d\n", pHeader.link_size_);
    569   fprintf(gOutFile, "link_off            : %d (0x%06x)\n",
    570           pHeader.link_off_, pHeader.link_off_);
    571   fprintf(gOutFile, "string_ids_size     : %d\n", pHeader.string_ids_size_);
    572   fprintf(gOutFile, "string_ids_off      : %d (0x%06x)\n",
    573           pHeader.string_ids_off_, pHeader.string_ids_off_);
    574   fprintf(gOutFile, "type_ids_size       : %d\n", pHeader.type_ids_size_);
    575   fprintf(gOutFile, "type_ids_off        : %d (0x%06x)\n",
    576           pHeader.type_ids_off_, pHeader.type_ids_off_);
    577   fprintf(gOutFile, "proto_ids_size      : %d\n", pHeader.proto_ids_size_);
    578   fprintf(gOutFile, "proto_ids_off       : %d (0x%06x)\n",
    579           pHeader.proto_ids_off_, pHeader.proto_ids_off_);
    580   fprintf(gOutFile, "field_ids_size      : %d\n", pHeader.field_ids_size_);
    581   fprintf(gOutFile, "field_ids_off       : %d (0x%06x)\n",
    582           pHeader.field_ids_off_, pHeader.field_ids_off_);
    583   fprintf(gOutFile, "method_ids_size     : %d\n", pHeader.method_ids_size_);
    584   fprintf(gOutFile, "method_ids_off      : %d (0x%06x)\n",
    585           pHeader.method_ids_off_, pHeader.method_ids_off_);
    586   fprintf(gOutFile, "class_defs_size     : %d\n", pHeader.class_defs_size_);
    587   fprintf(gOutFile, "class_defs_off      : %d (0x%06x)\n",
    588           pHeader.class_defs_off_, pHeader.class_defs_off_);
    589   fprintf(gOutFile, "data_size           : %d\n", pHeader.data_size_);
    590   fprintf(gOutFile, "data_off            : %d (0x%06x)\n\n",
    591           pHeader.data_off_, pHeader.data_off_);
    592 }
    593 
    594 /*
    595  * Dumps a class_def_item.
    596  */
    597 static void dumpClassDef(const DexFile* pDexFile, int idx) {
    598   // General class information.
    599   const DexFile::ClassDef& pClassDef = pDexFile->GetClassDef(idx);
    600   fprintf(gOutFile, "Class #%d header:\n", idx);
    601   fprintf(gOutFile, "class_idx           : %d\n", pClassDef.class_idx_.index_);
    602   fprintf(gOutFile, "access_flags        : %d (0x%04x)\n",
    603           pClassDef.access_flags_, pClassDef.access_flags_);
    604   fprintf(gOutFile, "superclass_idx      : %d\n", pClassDef.superclass_idx_.index_);
    605   fprintf(gOutFile, "interfaces_off      : %d (0x%06x)\n",
    606           pClassDef.interfaces_off_, pClassDef.interfaces_off_);
    607   fprintf(gOutFile, "source_file_idx     : %d\n", pClassDef.source_file_idx_.index_);
    608   fprintf(gOutFile, "annotations_off     : %d (0x%06x)\n",
    609           pClassDef.annotations_off_, pClassDef.annotations_off_);
    610   fprintf(gOutFile, "class_data_off      : %d (0x%06x)\n",
    611           pClassDef.class_data_off_, pClassDef.class_data_off_);
    612 
    613   // Fields and methods.
    614   const u1* pEncodedData = pDexFile->GetClassData(pClassDef);
    615   if (pEncodedData != nullptr) {
    616     ClassDataItemIterator pClassData(*pDexFile, pEncodedData);
    617     fprintf(gOutFile, "static_fields_size  : %d\n", pClassData.NumStaticFields());
    618     fprintf(gOutFile, "instance_fields_size: %d\n", pClassData.NumInstanceFields());
    619     fprintf(gOutFile, "direct_methods_size : %d\n", pClassData.NumDirectMethods());
    620     fprintf(gOutFile, "virtual_methods_size: %d\n", pClassData.NumVirtualMethods());
    621   } else {
    622     fprintf(gOutFile, "static_fields_size  : 0\n");
    623     fprintf(gOutFile, "instance_fields_size: 0\n");
    624     fprintf(gOutFile, "direct_methods_size : 0\n");
    625     fprintf(gOutFile, "virtual_methods_size: 0\n");
    626   }
    627   fprintf(gOutFile, "\n");
    628 }
    629 
    630 /**
    631  * Dumps an annotation set item.
    632  */
    633 static void dumpAnnotationSetItem(const DexFile* pDexFile, const DexFile::AnnotationSetItem* set_item) {
    634   if (set_item == nullptr || set_item->size_ == 0) {
    635     fputs("  empty-annotation-set\n", gOutFile);
    636     return;
    637   }
    638   for (u4 i = 0; i < set_item->size_; i++) {
    639     const DexFile::AnnotationItem* annotation = pDexFile->GetAnnotationItem(set_item, i);
    640     if (annotation == nullptr) {
    641       continue;
    642     }
    643     fputs("  ", gOutFile);
    644     switch (annotation->visibility_) {
    645       case DexFile::kDexVisibilityBuild:   fputs("VISIBILITY_BUILD ",   gOutFile); break;
    646       case DexFile::kDexVisibilityRuntime: fputs("VISIBILITY_RUNTIME ", gOutFile); break;
    647       case DexFile::kDexVisibilitySystem:  fputs("VISIBILITY_SYSTEM ",  gOutFile); break;
    648       default:                             fputs("VISIBILITY_UNKNOWN ", gOutFile); break;
    649     }  // switch
    650     // Decode raw bytes in annotation.
    651     const u1* rData = annotation->annotation_;
    652     dumpEncodedValue(pDexFile, &rData, DexFile::kDexAnnotationAnnotation, 0);
    653     fputc('\n', gOutFile);
    654   }
    655 }
    656 
    657 /*
    658  * Dumps class annotations.
    659  */
    660 static void dumpClassAnnotations(const DexFile* pDexFile, int idx) {
    661   const DexFile::ClassDef& pClassDef = pDexFile->GetClassDef(idx);
    662   const DexFile::AnnotationsDirectoryItem* dir = pDexFile->GetAnnotationsDirectory(pClassDef);
    663   if (dir == nullptr) {
    664     return;  // none
    665   }
    666 
    667   fprintf(gOutFile, "Class #%d annotations:\n", idx);
    668 
    669   const DexFile::AnnotationSetItem* class_set_item = pDexFile->GetClassAnnotationSet(dir);
    670   const DexFile::FieldAnnotationsItem* fields = pDexFile->GetFieldAnnotations(dir);
    671   const DexFile::MethodAnnotationsItem* methods = pDexFile->GetMethodAnnotations(dir);
    672   const DexFile::ParameterAnnotationsItem* pars = pDexFile->GetParameterAnnotations(dir);
    673 
    674   // Annotations on the class itself.
    675   if (class_set_item != nullptr) {
    676     fprintf(gOutFile, "Annotations on class\n");
    677     dumpAnnotationSetItem(pDexFile, class_set_item);
    678   }
    679 
    680   // Annotations on fields.
    681   if (fields != nullptr) {
    682     for (u4 i = 0; i < dir->fields_size_; i++) {
    683       const u4 field_idx = fields[i].field_idx_;
    684       const DexFile::FieldId& pFieldId = pDexFile->GetFieldId(field_idx);
    685       const char* field_name = pDexFile->StringDataByIdx(pFieldId.name_idx_);
    686       fprintf(gOutFile, "Annotations on field #%u '%s'\n", field_idx, field_name);
    687       dumpAnnotationSetItem(pDexFile, pDexFile->GetFieldAnnotationSetItem(fields[i]));
    688     }
    689   }
    690 
    691   // Annotations on methods.
    692   if (methods != nullptr) {
    693     for (u4 i = 0; i < dir->methods_size_; i++) {
    694       const u4 method_idx = methods[i].method_idx_;
    695       const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(method_idx);
    696       const char* method_name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
    697       fprintf(gOutFile, "Annotations on method #%u '%s'\n", method_idx, method_name);
    698       dumpAnnotationSetItem(pDexFile, pDexFile->GetMethodAnnotationSetItem(methods[i]));
    699     }
    700   }
    701 
    702   // Annotations on method parameters.
    703   if (pars != nullptr) {
    704     for (u4 i = 0; i < dir->parameters_size_; i++) {
    705       const u4 method_idx = pars[i].method_idx_;
    706       const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(method_idx);
    707       const char* method_name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
    708       fprintf(gOutFile, "Annotations on method #%u '%s' parameters\n", method_idx, method_name);
    709       const DexFile::AnnotationSetRefList*
    710           list = pDexFile->GetParameterAnnotationSetRefList(&pars[i]);
    711       if (list != nullptr) {
    712         for (u4 j = 0; j < list->size_; j++) {
    713           fprintf(gOutFile, "#%u\n", j);
    714           dumpAnnotationSetItem(pDexFile, pDexFile->GetSetRefItemItem(&list->list_[j]));
    715         }
    716       }
    717     }
    718   }
    719 
    720   fputc('\n', gOutFile);
    721 }
    722 
    723 /*
    724  * Dumps an interface that a class declares to implement.
    725  */
    726 static void dumpInterface(const DexFile* pDexFile, const DexFile::TypeItem& pTypeItem, int i) {
    727   const char* interfaceName = pDexFile->StringByTypeIdx(pTypeItem.type_idx_);
    728   if (gOptions.outputFormat == OUTPUT_PLAIN) {
    729     fprintf(gOutFile, "    #%d              : '%s'\n", i, interfaceName);
    730   } else {
    731     std::unique_ptr<char[]> dot(descriptorToDot(interfaceName));
    732     fprintf(gOutFile, "<implements name=\"%s\">\n</implements>\n", dot.get());
    733   }
    734 }
    735 
    736 /*
    737  * Dumps the catches table associated with the code.
    738  */
    739 static void dumpCatches(const DexFile* pDexFile, const DexFile::CodeItem* pCode) {
    740   CodeItemDataAccessor accessor(*pDexFile, pCode);
    741   const u4 triesSize = accessor.TriesSize();
    742 
    743   // No catch table.
    744   if (triesSize == 0) {
    745     fprintf(gOutFile, "      catches       : (none)\n");
    746     return;
    747   }
    748 
    749   // Dump all table entries.
    750   fprintf(gOutFile, "      catches       : %d\n", triesSize);
    751   for (const DexFile::TryItem& try_item : accessor.TryItems()) {
    752     const u4 start = try_item.start_addr_;
    753     const u4 end = start + try_item.insn_count_;
    754     fprintf(gOutFile, "        0x%04x - 0x%04x\n", start, end);
    755     for (CatchHandlerIterator it(accessor, try_item); it.HasNext(); it.Next()) {
    756       const dex::TypeIndex tidx = it.GetHandlerTypeIndex();
    757       const char* descriptor = (!tidx.IsValid()) ? "<any>" : pDexFile->StringByTypeIdx(tidx);
    758       fprintf(gOutFile, "          %s -> 0x%04x\n", descriptor, it.GetHandlerAddress());
    759     }  // for
    760   }  // for
    761 }
    762 
    763 /*
    764  * Callback for dumping each positions table entry.
    765  */
    766 static bool dumpPositionsCb(void* /*context*/, const DexFile::PositionInfo& entry) {
    767   fprintf(gOutFile, "        0x%04x line=%d\n", entry.address_, entry.line_);
    768   return false;
    769 }
    770 
    771 /*
    772  * Callback for dumping locals table entry.
    773  */
    774 static void dumpLocalsCb(void* /*context*/, const DexFile::LocalInfo& entry) {
    775   const char* signature = entry.signature_ != nullptr ? entry.signature_ : "";
    776   fprintf(gOutFile, "        0x%04x - 0x%04x reg=%d %s %s %s\n",
    777           entry.start_address_, entry.end_address_, entry.reg_,
    778           entry.name_, entry.descriptor_, signature);
    779 }
    780 
    781 /*
    782  * Helper for dumpInstruction(), which builds the string
    783  * representation for the index in the given instruction.
    784  * Returns a pointer to a buffer of sufficient size.
    785  */
    786 static std::unique_ptr<char[]> indexString(const DexFile* pDexFile,
    787                                            const Instruction* pDecInsn,
    788                                            size_t bufSize) {
    789   static const u4 kInvalidIndex = std::numeric_limits<u4>::max();
    790   std::unique_ptr<char[]> buf(new char[bufSize]);
    791   // Determine index and width of the string.
    792   u4 index = 0;
    793   u4 secondary_index = kInvalidIndex;
    794   u4 width = 4;
    795   switch (Instruction::FormatOf(pDecInsn->Opcode())) {
    796     // SOME NOT SUPPORTED:
    797     // case Instruction::k20bc:
    798     case Instruction::k21c:
    799     case Instruction::k35c:
    800     // case Instruction::k35ms:
    801     case Instruction::k3rc:
    802     // case Instruction::k3rms:
    803     // case Instruction::k35mi:
    804     // case Instruction::k3rmi:
    805       index = pDecInsn->VRegB();
    806       width = 4;
    807       break;
    808     case Instruction::k31c:
    809       index = pDecInsn->VRegB();
    810       width = 8;
    811       break;
    812     case Instruction::k22c:
    813     // case Instruction::k22cs:
    814       index = pDecInsn->VRegC();
    815       width = 4;
    816       break;
    817     case Instruction::k45cc:
    818     case Instruction::k4rcc:
    819       index = pDecInsn->VRegB();
    820       secondary_index = pDecInsn->VRegH();
    821       width = 4;
    822       break;
    823     default:
    824       break;
    825   }  // switch
    826 
    827   // Determine index type.
    828   size_t outSize = 0;
    829   switch (Instruction::IndexTypeOf(pDecInsn->Opcode())) {
    830     case Instruction::kIndexUnknown:
    831       // This function should never get called for this type, but do
    832       // something sensible here, just to help with debugging.
    833       outSize = snprintf(buf.get(), bufSize, "<unknown-index>");
    834       break;
    835     case Instruction::kIndexNone:
    836       // This function should never get called for this type, but do
    837       // something sensible here, just to help with debugging.
    838       outSize = snprintf(buf.get(), bufSize, "<no-index>");
    839       break;
    840     case Instruction::kIndexTypeRef:
    841       if (index < pDexFile->GetHeader().type_ids_size_) {
    842         const char* tp = pDexFile->StringByTypeIdx(dex::TypeIndex(index));
    843         outSize = snprintf(buf.get(), bufSize, "%s // type@%0*x", tp, width, index);
    844       } else {
    845         outSize = snprintf(buf.get(), bufSize, "<type?> // type@%0*x", width, index);
    846       }
    847       break;
    848     case Instruction::kIndexStringRef:
    849       if (index < pDexFile->GetHeader().string_ids_size_) {
    850         const char* st = pDexFile->StringDataByIdx(dex::StringIndex(index));
    851         outSize = snprintf(buf.get(), bufSize, "\"%s\" // string@%0*x", st, width, index);
    852       } else {
    853         outSize = snprintf(buf.get(), bufSize, "<string?> // string@%0*x", width, index);
    854       }
    855       break;
    856     case Instruction::kIndexMethodRef:
    857       if (index < pDexFile->GetHeader().method_ids_size_) {
    858         const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(index);
    859         const char* name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
    860         const Signature signature = pDexFile->GetMethodSignature(pMethodId);
    861         const char* backDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
    862         outSize = snprintf(buf.get(), bufSize, "%s.%s:%s // method@%0*x",
    863                            backDescriptor, name, signature.ToString().c_str(), width, index);
    864       } else {
    865         outSize = snprintf(buf.get(), bufSize, "<method?> // method@%0*x", width, index);
    866       }
    867       break;
    868     case Instruction::kIndexFieldRef:
    869       if (index < pDexFile->GetHeader().field_ids_size_) {
    870         const DexFile::FieldId& pFieldId = pDexFile->GetFieldId(index);
    871         const char* name = pDexFile->StringDataByIdx(pFieldId.name_idx_);
    872         const char* typeDescriptor = pDexFile->StringByTypeIdx(pFieldId.type_idx_);
    873         const char* backDescriptor = pDexFile->StringByTypeIdx(pFieldId.class_idx_);
    874         outSize = snprintf(buf.get(), bufSize, "%s.%s:%s // field@%0*x",
    875                            backDescriptor, name, typeDescriptor, width, index);
    876       } else {
    877         outSize = snprintf(buf.get(), bufSize, "<field?> // field@%0*x", width, index);
    878       }
    879       break;
    880     case Instruction::kIndexVtableOffset:
    881       outSize = snprintf(buf.get(), bufSize, "[%0*x] // vtable #%0*x",
    882                          width, index, width, index);
    883       break;
    884     case Instruction::kIndexFieldOffset:
    885       outSize = snprintf(buf.get(), bufSize, "[obj+%0*x]", width, index);
    886       break;
    887     case Instruction::kIndexMethodAndProtoRef: {
    888       std::string method("<method?>");
    889       std::string proto("<proto?>");
    890       if (index < pDexFile->GetHeader().method_ids_size_) {
    891         const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(index);
    892         const char* name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
    893         const Signature signature = pDexFile->GetMethodSignature(pMethodId);
    894         const char* backDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
    895         method = android::base::StringPrintf("%s.%s:%s",
    896                                              backDescriptor,
    897                                              name,
    898                                              signature.ToString().c_str());
    899       }
    900       if (secondary_index < pDexFile->GetHeader().proto_ids_size_) {
    901         const DexFile::ProtoId& protoId = pDexFile->GetProtoId(secondary_index);
    902         const Signature signature = pDexFile->GetProtoSignature(protoId);
    903         proto = signature.ToString();
    904       }
    905       outSize = snprintf(buf.get(), bufSize, "%s, %s // method@%0*x, proto@%0*x",
    906                          method.c_str(), proto.c_str(), width, index, width, secondary_index);
    907       break;
    908     }
    909     case Instruction::kIndexCallSiteRef:
    910       // Call site information is too large to detail in disassembly so just output the index.
    911       outSize = snprintf(buf.get(), bufSize, "call_site@%0*x", width, index);
    912       break;
    913     case Instruction::kIndexMethodHandleRef:
    914       // Method handle information is too large to detail in disassembly so just output the index.
    915       outSize = snprintf(buf.get(), bufSize, "method_handle@%0*x", width, index);
    916       break;
    917     case Instruction::kIndexProtoRef:
    918       if (index < pDexFile->GetHeader().proto_ids_size_) {
    919         const DexFile::ProtoId& protoId = pDexFile->GetProtoId(index);
    920         const Signature signature = pDexFile->GetProtoSignature(protoId);
    921         const std::string& proto = signature.ToString();
    922         outSize = snprintf(buf.get(), bufSize, "%s // proto@%0*x", proto.c_str(), width, index);
    923       } else {
    924         outSize = snprintf(buf.get(), bufSize, "<?> // proto@%0*x", width, index);
    925       }
    926       break;
    927   }  // switch
    928 
    929   if (outSize == 0) {
    930     // The index type has not been handled in the switch above.
    931     outSize = snprintf(buf.get(), bufSize, "<?>");
    932   }
    933 
    934   // Determine success of string construction.
    935   if (outSize >= bufSize) {
    936     // The buffer wasn't big enough; retry with computed size. Note: snprintf()
    937     // doesn't count/ the '\0' as part of its returned size, so we add explicit
    938     // space for it here.
    939     return indexString(pDexFile, pDecInsn, outSize + 1);
    940   }
    941   return buf;
    942 }
    943 
    944 /*
    945  * Dumps a single instruction.
    946  */
    947 static void dumpInstruction(const DexFile* pDexFile,
    948                             const DexFile::CodeItem* pCode,
    949                             u4 codeOffset, u4 insnIdx, u4 insnWidth,
    950                             const Instruction* pDecInsn) {
    951   // Address of instruction (expressed as byte offset).
    952   fprintf(gOutFile, "%06x:", codeOffset + 0x10 + insnIdx * 2);
    953 
    954   // Dump (part of) raw bytes.
    955   CodeItemInstructionAccessor accessor(*pDexFile, pCode);
    956   for (u4 i = 0; i < 8; i++) {
    957     if (i < insnWidth) {
    958       if (i == 7) {
    959         fprintf(gOutFile, " ... ");
    960       } else {
    961         // Print 16-bit value in little-endian order.
    962         const u1* bytePtr = (const u1*) &accessor.Insns()[insnIdx + i];
    963         fprintf(gOutFile, " %02x%02x", bytePtr[0], bytePtr[1]);
    964       }
    965     } else {
    966       fputs("     ", gOutFile);
    967     }
    968   }  // for
    969 
    970   // Dump pseudo-instruction or opcode.
    971   if (pDecInsn->Opcode() == Instruction::NOP) {
    972     const u2 instr = get2LE((const u1*) &accessor.Insns()[insnIdx]);
    973     if (instr == Instruction::kPackedSwitchSignature) {
    974       fprintf(gOutFile, "|%04x: packed-switch-data (%d units)", insnIdx, insnWidth);
    975     } else if (instr == Instruction::kSparseSwitchSignature) {
    976       fprintf(gOutFile, "|%04x: sparse-switch-data (%d units)", insnIdx, insnWidth);
    977     } else if (instr == Instruction::kArrayDataSignature) {
    978       fprintf(gOutFile, "|%04x: array-data (%d units)", insnIdx, insnWidth);
    979     } else {
    980       fprintf(gOutFile, "|%04x: nop // spacer", insnIdx);
    981     }
    982   } else {
    983     fprintf(gOutFile, "|%04x: %s", insnIdx, pDecInsn->Name());
    984   }
    985 
    986   // Set up additional argument.
    987   std::unique_ptr<char[]> indexBuf;
    988   if (Instruction::IndexTypeOf(pDecInsn->Opcode()) != Instruction::kIndexNone) {
    989     indexBuf = indexString(pDexFile, pDecInsn, 200);
    990   }
    991 
    992   // Dump the instruction.
    993   //
    994   // NOTE: pDecInsn->DumpString(pDexFile) differs too much from original.
    995   //
    996   switch (Instruction::FormatOf(pDecInsn->Opcode())) {
    997     case Instruction::k10x:        // op
    998       break;
    999     case Instruction::k12x:        // op vA, vB
   1000       fprintf(gOutFile, " v%d, v%d", pDecInsn->VRegA(), pDecInsn->VRegB());
   1001       break;
   1002     case Instruction::k11n:        // op vA, #+B
   1003       fprintf(gOutFile, " v%d, #int %d // #%x",
   1004               pDecInsn->VRegA(), (s4) pDecInsn->VRegB(), (u1)pDecInsn->VRegB());
   1005       break;
   1006     case Instruction::k11x:        // op vAA
   1007       fprintf(gOutFile, " v%d", pDecInsn->VRegA());
   1008       break;
   1009     case Instruction::k10t:        // op +AA
   1010     case Instruction::k20t: {      // op +AAAA
   1011       const s4 targ = (s4) pDecInsn->VRegA();
   1012       fprintf(gOutFile, " %04x // %c%04x",
   1013               insnIdx + targ,
   1014               (targ < 0) ? '-' : '+',
   1015               (targ < 0) ? -targ : targ);
   1016       break;
   1017     }
   1018     case Instruction::k22x:        // op vAA, vBBBB
   1019       fprintf(gOutFile, " v%d, v%d", pDecInsn->VRegA(), pDecInsn->VRegB());
   1020       break;
   1021     case Instruction::k21t: {     // op vAA, +BBBB
   1022       const s4 targ = (s4) pDecInsn->VRegB();
   1023       fprintf(gOutFile, " v%d, %04x // %c%04x", pDecInsn->VRegA(),
   1024               insnIdx + targ,
   1025               (targ < 0) ? '-' : '+',
   1026               (targ < 0) ? -targ : targ);
   1027       break;
   1028     }
   1029     case Instruction::k21s:        // op vAA, #+BBBB
   1030       fprintf(gOutFile, " v%d, #int %d // #%x",
   1031               pDecInsn->VRegA(), (s4) pDecInsn->VRegB(), (u2)pDecInsn->VRegB());
   1032       break;
   1033     case Instruction::k21h:        // op vAA, #+BBBB0000[00000000]
   1034       // The printed format varies a bit based on the actual opcode.
   1035       if (pDecInsn->Opcode() == Instruction::CONST_HIGH16) {
   1036         const s4 value = pDecInsn->VRegB() << 16;
   1037         fprintf(gOutFile, " v%d, #int %d // #%x",
   1038                 pDecInsn->VRegA(), value, (u2) pDecInsn->VRegB());
   1039       } else {
   1040         const s8 value = ((s8) pDecInsn->VRegB()) << 48;
   1041         fprintf(gOutFile, " v%d, #long %" PRId64 " // #%x",
   1042                 pDecInsn->VRegA(), value, (u2) pDecInsn->VRegB());
   1043       }
   1044       break;
   1045     case Instruction::k21c:        // op vAA, thing@BBBB
   1046     case Instruction::k31c:        // op vAA, thing@BBBBBBBB
   1047       fprintf(gOutFile, " v%d, %s", pDecInsn->VRegA(), indexBuf.get());
   1048       break;
   1049     case Instruction::k23x:        // op vAA, vBB, vCC
   1050       fprintf(gOutFile, " v%d, v%d, v%d",
   1051               pDecInsn->VRegA(), pDecInsn->VRegB(), pDecInsn->VRegC());
   1052       break;
   1053     case Instruction::k22b:        // op vAA, vBB, #+CC
   1054       fprintf(gOutFile, " v%d, v%d, #int %d // #%02x",
   1055               pDecInsn->VRegA(), pDecInsn->VRegB(),
   1056               (s4) pDecInsn->VRegC(), (u1) pDecInsn->VRegC());
   1057       break;
   1058     case Instruction::k22t: {      // op vA, vB, +CCCC
   1059       const s4 targ = (s4) pDecInsn->VRegC();
   1060       fprintf(gOutFile, " v%d, v%d, %04x // %c%04x",
   1061               pDecInsn->VRegA(), pDecInsn->VRegB(),
   1062               insnIdx + targ,
   1063               (targ < 0) ? '-' : '+',
   1064               (targ < 0) ? -targ : targ);
   1065       break;
   1066     }
   1067     case Instruction::k22s:        // op vA, vB, #+CCCC
   1068       fprintf(gOutFile, " v%d, v%d, #int %d // #%04x",
   1069               pDecInsn->VRegA(), pDecInsn->VRegB(),
   1070               (s4) pDecInsn->VRegC(), (u2) pDecInsn->VRegC());
   1071       break;
   1072     case Instruction::k22c:        // op vA, vB, thing@CCCC
   1073     // NOT SUPPORTED:
   1074     // case Instruction::k22cs:    // [opt] op vA, vB, field offset CCCC
   1075       fprintf(gOutFile, " v%d, v%d, %s",
   1076               pDecInsn->VRegA(), pDecInsn->VRegB(), indexBuf.get());
   1077       break;
   1078     case Instruction::k30t:
   1079       fprintf(gOutFile, " #%08x", pDecInsn->VRegA());
   1080       break;
   1081     case Instruction::k31i: {     // op vAA, #+BBBBBBBB
   1082       // This is often, but not always, a float.
   1083       union {
   1084         float f;
   1085         u4 i;
   1086       } conv;
   1087       conv.i = pDecInsn->VRegB();
   1088       fprintf(gOutFile, " v%d, #float %g // #%08x",
   1089               pDecInsn->VRegA(), conv.f, pDecInsn->VRegB());
   1090       break;
   1091     }
   1092     case Instruction::k31t:       // op vAA, offset +BBBBBBBB
   1093       fprintf(gOutFile, " v%d, %08x // +%08x",
   1094               pDecInsn->VRegA(), insnIdx + pDecInsn->VRegB(), pDecInsn->VRegB());
   1095       break;
   1096     case Instruction::k32x:        // op vAAAA, vBBBB
   1097       fprintf(gOutFile, " v%d, v%d", pDecInsn->VRegA(), pDecInsn->VRegB());
   1098       break;
   1099     case Instruction::k35c:       // op {vC, vD, vE, vF, vG}, thing@BBBB
   1100     case Instruction::k45cc: {    // op {vC, vD, vE, vF, vG}, method@BBBB, proto@HHHH
   1101     // NOT SUPPORTED:
   1102     // case Instruction::k35ms:       // [opt] invoke-virtual+super
   1103     // case Instruction::k35mi:       // [opt] inline invoke
   1104       u4 arg[Instruction::kMaxVarArgRegs];
   1105       pDecInsn->GetVarArgs(arg);
   1106       fputs(" {", gOutFile);
   1107       for (int i = 0, n = pDecInsn->VRegA(); i < n; i++) {
   1108         if (i == 0) {
   1109           fprintf(gOutFile, "v%d", arg[i]);
   1110         } else {
   1111           fprintf(gOutFile, ", v%d", arg[i]);
   1112         }
   1113       }  // for
   1114       fprintf(gOutFile, "}, %s", indexBuf.get());
   1115       break;
   1116     }
   1117     case Instruction::k3rc:        // op {vCCCC .. v(CCCC+AA-1)}, thing@BBBB
   1118     case Instruction::k4rcc: {     // op {vCCCC .. v(CCCC+AA-1)}, method@BBBB, proto@HHHH
   1119     // NOT SUPPORTED:
   1120     // case Instruction::k3rms:       // [opt] invoke-virtual+super/range
   1121     // case Instruction::k3rmi:       // [opt] execute-inline/range
   1122         // This doesn't match the "dx" output when some of the args are
   1123         // 64-bit values -- dx only shows the first register.
   1124         fputs(" {", gOutFile);
   1125         for (int i = 0, n = pDecInsn->VRegA(); i < n; i++) {
   1126           if (i == 0) {
   1127             fprintf(gOutFile, "v%d", pDecInsn->VRegC() + i);
   1128           } else {
   1129             fprintf(gOutFile, ", v%d", pDecInsn->VRegC() + i);
   1130           }
   1131         }  // for
   1132         fprintf(gOutFile, "}, %s", indexBuf.get());
   1133       }
   1134       break;
   1135     case Instruction::k51l: {      // op vAA, #+BBBBBBBBBBBBBBBB
   1136       // This is often, but not always, a double.
   1137       union {
   1138         double d;
   1139         u8 j;
   1140       } conv;
   1141       conv.j = pDecInsn->WideVRegB();
   1142       fprintf(gOutFile, " v%d, #double %g // #%016" PRIx64,
   1143               pDecInsn->VRegA(), conv.d, pDecInsn->WideVRegB());
   1144       break;
   1145     }
   1146     // NOT SUPPORTED:
   1147     // case Instruction::k00x:        // unknown op or breakpoint
   1148     //    break;
   1149     default:
   1150       fprintf(gOutFile, " ???");
   1151       break;
   1152   }  // switch
   1153 
   1154   fputc('\n', gOutFile);
   1155 }
   1156 
   1157 /*
   1158  * Dumps a bytecode disassembly.
   1159  */
   1160 static void dumpBytecodes(const DexFile* pDexFile, u4 idx,
   1161                           const DexFile::CodeItem* pCode, u4 codeOffset) {
   1162   const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(idx);
   1163   const char* name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
   1164   const Signature signature = pDexFile->GetMethodSignature(pMethodId);
   1165   const char* backDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
   1166 
   1167   // Generate header.
   1168   std::unique_ptr<char[]> dot(descriptorToDot(backDescriptor));
   1169   fprintf(gOutFile, "%06x:                                        |[%06x] %s.%s:%s\n",
   1170           codeOffset, codeOffset, dot.get(), name, signature.ToString().c_str());
   1171 
   1172   // Iterate over all instructions.
   1173   CodeItemDataAccessor accessor(*pDexFile, pCode);
   1174   const u4 maxPc = accessor.InsnsSizeInCodeUnits();
   1175   for (const DexInstructionPcPair& pair : accessor) {
   1176     const u4 dexPc = pair.DexPc();
   1177     if (dexPc >= maxPc) {
   1178       LOG(WARNING) << "GLITCH: run-away instruction at idx=0x" << std::hex << dexPc;
   1179       break;
   1180     }
   1181     const Instruction* instruction = &pair.Inst();
   1182     const u4 insnWidth = instruction->SizeInCodeUnits();
   1183     if (insnWidth == 0) {
   1184       LOG(WARNING) << "GLITCH: zero-width instruction at idx=0x" << std::hex << dexPc;
   1185       break;
   1186     }
   1187     dumpInstruction(pDexFile, pCode, codeOffset, dexPc, insnWidth, instruction);
   1188   }  // for
   1189 }
   1190 
   1191 /*
   1192  * Dumps code of a method.
   1193  */
   1194 static void dumpCode(const DexFile* pDexFile, u4 idx, u4 flags,
   1195                      const DexFile::CodeItem* pCode, u4 codeOffset) {
   1196   CodeItemDebugInfoAccessor accessor(*pDexFile, pCode, idx);
   1197 
   1198   fprintf(gOutFile, "      registers     : %d\n", accessor.RegistersSize());
   1199   fprintf(gOutFile, "      ins           : %d\n", accessor.InsSize());
   1200   fprintf(gOutFile, "      outs          : %d\n", accessor.OutsSize());
   1201   fprintf(gOutFile, "      insns size    : %d 16-bit code units\n",
   1202           accessor.InsnsSizeInCodeUnits());
   1203 
   1204   // Bytecode disassembly, if requested.
   1205   if (gOptions.disassemble) {
   1206     dumpBytecodes(pDexFile, idx, pCode, codeOffset);
   1207   }
   1208 
   1209   // Try-catch blocks.
   1210   dumpCatches(pDexFile, pCode);
   1211 
   1212   // Positions and locals table in the debug info.
   1213   bool is_static = (flags & kAccStatic) != 0;
   1214   fprintf(gOutFile, "      positions     : \n");
   1215   pDexFile->DecodeDebugPositionInfo(accessor.DebugInfoOffset(), dumpPositionsCb, nullptr);
   1216   fprintf(gOutFile, "      locals        : \n");
   1217   accessor.DecodeDebugLocalInfo(is_static, idx, dumpLocalsCb, nullptr);
   1218 }
   1219 
   1220 /*
   1221  * Dumps a method.
   1222  */
   1223 static void dumpMethod(const DexFile* pDexFile, u4 idx, u4 flags,
   1224                        const DexFile::CodeItem* pCode, u4 codeOffset, int i) {
   1225   // Bail for anything private if export only requested.
   1226   if (gOptions.exportsOnly && (flags & (kAccPublic | kAccProtected)) == 0) {
   1227     return;
   1228   }
   1229 
   1230   const DexFile::MethodId& pMethodId = pDexFile->GetMethodId(idx);
   1231   const char* name = pDexFile->StringDataByIdx(pMethodId.name_idx_);
   1232   const Signature signature = pDexFile->GetMethodSignature(pMethodId);
   1233   char* typeDescriptor = strdup(signature.ToString().c_str());
   1234   const char* backDescriptor = pDexFile->StringByTypeIdx(pMethodId.class_idx_);
   1235   char* accessStr = createAccessFlagStr(flags, kAccessForMethod);
   1236 
   1237   if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1238     fprintf(gOutFile, "    #%d              : (in %s)\n", i, backDescriptor);
   1239     fprintf(gOutFile, "      name          : '%s'\n", name);
   1240     fprintf(gOutFile, "      type          : '%s'\n", typeDescriptor);
   1241     fprintf(gOutFile, "      access        : 0x%04x (%s)\n", flags, accessStr);
   1242     if (pCode == nullptr) {
   1243       fprintf(gOutFile, "      code          : (none)\n");
   1244     } else {
   1245       fprintf(gOutFile, "      code          -\n");
   1246       dumpCode(pDexFile, idx, flags, pCode, codeOffset);
   1247     }
   1248     if (gOptions.disassemble) {
   1249       fputc('\n', gOutFile);
   1250     }
   1251   } else if (gOptions.outputFormat == OUTPUT_XML) {
   1252     const bool constructor = (name[0] == '<');
   1253 
   1254     // Method name and prototype.
   1255     if (constructor) {
   1256       std::unique_ptr<char[]> dot(descriptorClassToDot(backDescriptor));
   1257       fprintf(gOutFile, "<constructor name=\"%s\"\n", dot.get());
   1258       dot = descriptorToDot(backDescriptor);
   1259       fprintf(gOutFile, " type=\"%s\"\n", dot.get());
   1260     } else {
   1261       fprintf(gOutFile, "<method name=\"%s\"\n", name);
   1262       const char* returnType = strrchr(typeDescriptor, ')');
   1263       if (returnType == nullptr) {
   1264         LOG(ERROR) << "bad method type descriptor '" << typeDescriptor << "'";
   1265         goto bail;
   1266       }
   1267       std::unique_ptr<char[]> dot(descriptorToDot(returnType + 1));
   1268       fprintf(gOutFile, " return=\"%s\"\n", dot.get());
   1269       fprintf(gOutFile, " abstract=%s\n", quotedBool((flags & kAccAbstract) != 0));
   1270       fprintf(gOutFile, " native=%s\n", quotedBool((flags & kAccNative) != 0));
   1271       fprintf(gOutFile, " synchronized=%s\n", quotedBool(
   1272           (flags & (kAccSynchronized | kAccDeclaredSynchronized)) != 0));
   1273     }
   1274 
   1275     // Additional method flags.
   1276     fprintf(gOutFile, " static=%s\n", quotedBool((flags & kAccStatic) != 0));
   1277     fprintf(gOutFile, " final=%s\n", quotedBool((flags & kAccFinal) != 0));
   1278     // The "deprecated=" not knowable w/o parsing annotations.
   1279     fprintf(gOutFile, " visibility=%s\n>\n", quotedVisibility(flags));
   1280 
   1281     // Parameters.
   1282     if (typeDescriptor[0] != '(') {
   1283       LOG(ERROR) << "ERROR: bad descriptor '" << typeDescriptor << "'";
   1284       goto bail;
   1285     }
   1286     char* tmpBuf = reinterpret_cast<char*>(malloc(strlen(typeDescriptor) + 1));
   1287     const char* base = typeDescriptor + 1;
   1288     int argNum = 0;
   1289     while (*base != ')') {
   1290       char* cp = tmpBuf;
   1291       while (*base == '[') {
   1292         *cp++ = *base++;
   1293       }
   1294       if (*base == 'L') {
   1295         // Copy through ';'.
   1296         do {
   1297           *cp = *base++;
   1298         } while (*cp++ != ';');
   1299       } else {
   1300         // Primitive char, copy it.
   1301         if (strchr("ZBCSIFJD", *base) == nullptr) {
   1302           LOG(ERROR) << "ERROR: bad method signature '" << base << "'";
   1303           break;  // while
   1304         }
   1305         *cp++ = *base++;
   1306       }
   1307       // Null terminate and display.
   1308       *cp++ = '\0';
   1309       std::unique_ptr<char[]> dot(descriptorToDot(tmpBuf));
   1310       fprintf(gOutFile, "<parameter name=\"arg%d\" type=\"%s\">\n"
   1311                         "</parameter>\n", argNum++, dot.get());
   1312     }  // while
   1313     free(tmpBuf);
   1314     if (constructor) {
   1315       fprintf(gOutFile, "</constructor>\n");
   1316     } else {
   1317       fprintf(gOutFile, "</method>\n");
   1318     }
   1319   }
   1320 
   1321  bail:
   1322   free(typeDescriptor);
   1323   free(accessStr);
   1324 }
   1325 
   1326 /*
   1327  * Dumps a static (class) field.
   1328  */
   1329 static void dumpSField(const DexFile* pDexFile, u4 idx, u4 flags, int i, const u1** data) {
   1330   // Bail for anything private if export only requested.
   1331   if (gOptions.exportsOnly && (flags & (kAccPublic | kAccProtected)) == 0) {
   1332     return;
   1333   }
   1334 
   1335   const DexFile::FieldId& pFieldId = pDexFile->GetFieldId(idx);
   1336   const char* name = pDexFile->StringDataByIdx(pFieldId.name_idx_);
   1337   const char* typeDescriptor = pDexFile->StringByTypeIdx(pFieldId.type_idx_);
   1338   const char* backDescriptor = pDexFile->StringByTypeIdx(pFieldId.class_idx_);
   1339   char* accessStr = createAccessFlagStr(flags, kAccessForField);
   1340 
   1341   if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1342     fprintf(gOutFile, "    #%d              : (in %s)\n", i, backDescriptor);
   1343     fprintf(gOutFile, "      name          : '%s'\n", name);
   1344     fprintf(gOutFile, "      type          : '%s'\n", typeDescriptor);
   1345     fprintf(gOutFile, "      access        : 0x%04x (%s)\n", flags, accessStr);
   1346     if (data != nullptr) {
   1347       fputs("      value         : ", gOutFile);
   1348       dumpEncodedValue(pDexFile, data);
   1349       fputs("\n", gOutFile);
   1350     }
   1351   } else if (gOptions.outputFormat == OUTPUT_XML) {
   1352     fprintf(gOutFile, "<field name=\"%s\"\n", name);
   1353     std::unique_ptr<char[]> dot(descriptorToDot(typeDescriptor));
   1354     fprintf(gOutFile, " type=\"%s\"\n", dot.get());
   1355     fprintf(gOutFile, " transient=%s\n", quotedBool((flags & kAccTransient) != 0));
   1356     fprintf(gOutFile, " volatile=%s\n", quotedBool((flags & kAccVolatile) != 0));
   1357     // The "value=" is not knowable w/o parsing annotations.
   1358     fprintf(gOutFile, " static=%s\n", quotedBool((flags & kAccStatic) != 0));
   1359     fprintf(gOutFile, " final=%s\n", quotedBool((flags & kAccFinal) != 0));
   1360     // The "deprecated=" is not knowable w/o parsing annotations.
   1361     fprintf(gOutFile, " visibility=%s\n", quotedVisibility(flags));
   1362     if (data != nullptr) {
   1363       fputs(" value=\"", gOutFile);
   1364       dumpEncodedValue(pDexFile, data);
   1365       fputs("\"\n", gOutFile);
   1366     }
   1367     fputs(">\n</field>\n", gOutFile);
   1368   }
   1369 
   1370   free(accessStr);
   1371 }
   1372 
   1373 /*
   1374  * Dumps an instance field.
   1375  */
   1376 static void dumpIField(const DexFile* pDexFile, u4 idx, u4 flags, int i) {
   1377   dumpSField(pDexFile, idx, flags, i, nullptr);
   1378 }
   1379 
   1380 /*
   1381  * Dumping a CFG. Note that this will do duplicate work. utils.h doesn't expose the code-item
   1382  * version, so the DumpMethodCFG code will have to iterate again to find it. But dexdump is a
   1383  * tool, so this is not performance-critical.
   1384  */
   1385 
   1386 static void dumpCfg(const DexFile* dex_file,
   1387                     u4 dex_method_idx,
   1388                     const DexFile::CodeItem* code_item) {
   1389   if (code_item != nullptr) {
   1390     std::ostringstream oss;
   1391     DumpMethodCFG(dex_file, dex_method_idx, oss);
   1392     fputs(oss.str().c_str(), gOutFile);
   1393   }
   1394 }
   1395 
   1396 static void dumpCfg(const DexFile* dex_file, int idx) {
   1397   const DexFile::ClassDef& class_def = dex_file->GetClassDef(idx);
   1398   const u1* class_data = dex_file->GetClassData(class_def);
   1399   if (class_data == nullptr) {  // empty class such as a marker interface?
   1400     return;
   1401   }
   1402   ClassDataItemIterator it(*dex_file, class_data);
   1403   it.SkipAllFields();
   1404   while (it.HasNextMethod()) {
   1405     dumpCfg(dex_file,
   1406             it.GetMemberIndex(),
   1407             it.GetMethodCodeItem());
   1408     it.Next();
   1409   }
   1410 }
   1411 
   1412 /*
   1413  * Dumps the class.
   1414  *
   1415  * Note "idx" is a DexClassDef index, not a DexTypeId index.
   1416  *
   1417  * If "*pLastPackage" is nullptr or does not match the current class' package,
   1418  * the value will be replaced with a newly-allocated string.
   1419  */
   1420 static void dumpClass(const DexFile* pDexFile, int idx, char** pLastPackage) {
   1421   const DexFile::ClassDef& pClassDef = pDexFile->GetClassDef(idx);
   1422 
   1423   // Omitting non-public class.
   1424   if (gOptions.exportsOnly && (pClassDef.access_flags_ & kAccPublic) == 0) {
   1425     return;
   1426   }
   1427 
   1428   if (gOptions.showSectionHeaders) {
   1429     dumpClassDef(pDexFile, idx);
   1430   }
   1431 
   1432   if (gOptions.showAnnotations) {
   1433     dumpClassAnnotations(pDexFile, idx);
   1434   }
   1435 
   1436   if (gOptions.showCfg) {
   1437     dumpCfg(pDexFile, idx);
   1438     return;
   1439   }
   1440 
   1441   // For the XML output, show the package name.  Ideally we'd gather
   1442   // up the classes, sort them, and dump them alphabetically so the
   1443   // package name wouldn't jump around, but that's not a great plan
   1444   // for something that needs to run on the device.
   1445   const char* classDescriptor = pDexFile->StringByTypeIdx(pClassDef.class_idx_);
   1446   if (!(classDescriptor[0] == 'L' &&
   1447         classDescriptor[strlen(classDescriptor)-1] == ';')) {
   1448     // Arrays and primitives should not be defined explicitly. Keep going?
   1449     LOG(WARNING) << "Malformed class name '" << classDescriptor << "'";
   1450   } else if (gOptions.outputFormat == OUTPUT_XML) {
   1451     char* mangle = strdup(classDescriptor + 1);
   1452     mangle[strlen(mangle)-1] = '\0';
   1453 
   1454     // Reduce to just the package name.
   1455     char* lastSlash = strrchr(mangle, '/');
   1456     if (lastSlash != nullptr) {
   1457       *lastSlash = '\0';
   1458     } else {
   1459       *mangle = '\0';
   1460     }
   1461 
   1462     for (char* cp = mangle; *cp != '\0'; cp++) {
   1463       if (*cp == '/') {
   1464         *cp = '.';
   1465       }
   1466     }  // for
   1467 
   1468     if (*pLastPackage == nullptr || strcmp(mangle, *pLastPackage) != 0) {
   1469       // Start of a new package.
   1470       if (*pLastPackage != nullptr) {
   1471         fprintf(gOutFile, "</package>\n");
   1472       }
   1473       fprintf(gOutFile, "<package name=\"%s\"\n>\n", mangle);
   1474       free(*pLastPackage);
   1475       *pLastPackage = mangle;
   1476     } else {
   1477       free(mangle);
   1478     }
   1479   }
   1480 
   1481   // General class information.
   1482   char* accessStr = createAccessFlagStr(pClassDef.access_flags_, kAccessForClass);
   1483   const char* superclassDescriptor;
   1484   if (!pClassDef.superclass_idx_.IsValid()) {
   1485     superclassDescriptor = nullptr;
   1486   } else {
   1487     superclassDescriptor = pDexFile->StringByTypeIdx(pClassDef.superclass_idx_);
   1488   }
   1489   if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1490     fprintf(gOutFile, "Class #%d            -\n", idx);
   1491     fprintf(gOutFile, "  Class descriptor  : '%s'\n", classDescriptor);
   1492     fprintf(gOutFile, "  Access flags      : 0x%04x (%s)\n", pClassDef.access_flags_, accessStr);
   1493     if (superclassDescriptor != nullptr) {
   1494       fprintf(gOutFile, "  Superclass        : '%s'\n", superclassDescriptor);
   1495     }
   1496     fprintf(gOutFile, "  Interfaces        -\n");
   1497   } else {
   1498     std::unique_ptr<char[]> dot(descriptorClassToDot(classDescriptor));
   1499     fprintf(gOutFile, "<class name=\"%s\"\n", dot.get());
   1500     if (superclassDescriptor != nullptr) {
   1501       dot = descriptorToDot(superclassDescriptor);
   1502       fprintf(gOutFile, " extends=\"%s\"\n", dot.get());
   1503     }
   1504     fprintf(gOutFile, " interface=%s\n",
   1505             quotedBool((pClassDef.access_flags_ & kAccInterface) != 0));
   1506     fprintf(gOutFile, " abstract=%s\n", quotedBool((pClassDef.access_flags_ & kAccAbstract) != 0));
   1507     fprintf(gOutFile, " static=%s\n", quotedBool((pClassDef.access_flags_ & kAccStatic) != 0));
   1508     fprintf(gOutFile, " final=%s\n", quotedBool((pClassDef.access_flags_ & kAccFinal) != 0));
   1509     // The "deprecated=" not knowable w/o parsing annotations.
   1510     fprintf(gOutFile, " visibility=%s\n", quotedVisibility(pClassDef.access_flags_));
   1511     fprintf(gOutFile, ">\n");
   1512   }
   1513 
   1514   // Interfaces.
   1515   const DexFile::TypeList* pInterfaces = pDexFile->GetInterfacesList(pClassDef);
   1516   if (pInterfaces != nullptr) {
   1517     for (u4 i = 0; i < pInterfaces->Size(); i++) {
   1518       dumpInterface(pDexFile, pInterfaces->GetTypeItem(i), i);
   1519     }  // for
   1520   }
   1521 
   1522   // Fields and methods.
   1523   const u1* pEncodedData = pDexFile->GetClassData(pClassDef);
   1524   if (pEncodedData == nullptr) {
   1525     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1526       fprintf(gOutFile, "  Static fields     -\n");
   1527       fprintf(gOutFile, "  Instance fields   -\n");
   1528       fprintf(gOutFile, "  Direct methods    -\n");
   1529       fprintf(gOutFile, "  Virtual methods   -\n");
   1530     }
   1531   } else {
   1532     ClassDataItemIterator pClassData(*pDexFile, pEncodedData);
   1533 
   1534     // Prepare data for static fields.
   1535     const u1* sData = pDexFile->GetEncodedStaticFieldValuesArray(pClassDef);
   1536     const u4 sSize = sData != nullptr ? DecodeUnsignedLeb128(&sData) : 0;
   1537 
   1538     // Static fields.
   1539     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1540       fprintf(gOutFile, "  Static fields     -\n");
   1541     }
   1542     for (u4 i = 0; pClassData.HasNextStaticField(); i++, pClassData.Next()) {
   1543       dumpSField(pDexFile,
   1544                  pClassData.GetMemberIndex(),
   1545                  pClassData.GetRawMemberAccessFlags(),
   1546                  i,
   1547                  i < sSize ? &sData : nullptr);
   1548     }  // for
   1549 
   1550     // Instance fields.
   1551     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1552       fprintf(gOutFile, "  Instance fields   -\n");
   1553     }
   1554     for (u4 i = 0; pClassData.HasNextInstanceField(); i++, pClassData.Next()) {
   1555       dumpIField(pDexFile,
   1556                  pClassData.GetMemberIndex(),
   1557                  pClassData.GetRawMemberAccessFlags(),
   1558                  i);
   1559     }  // for
   1560 
   1561     // Direct methods.
   1562     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1563       fprintf(gOutFile, "  Direct methods    -\n");
   1564     }
   1565     for (int i = 0; pClassData.HasNextDirectMethod(); i++, pClassData.Next()) {
   1566       dumpMethod(pDexFile, pClassData.GetMemberIndex(),
   1567                            pClassData.GetRawMemberAccessFlags(),
   1568                            pClassData.GetMethodCodeItem(),
   1569                            pClassData.GetMethodCodeItemOffset(), i);
   1570     }  // for
   1571 
   1572     // Virtual methods.
   1573     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1574       fprintf(gOutFile, "  Virtual methods   -\n");
   1575     }
   1576     for (int i = 0; pClassData.HasNextVirtualMethod(); i++, pClassData.Next()) {
   1577       dumpMethod(pDexFile, pClassData.GetMemberIndex(),
   1578                            pClassData.GetRawMemberAccessFlags(),
   1579                            pClassData.GetMethodCodeItem(),
   1580                            pClassData.GetMethodCodeItemOffset(), i);
   1581     }  // for
   1582   }
   1583 
   1584   // End of class.
   1585   if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1586     const char* fileName;
   1587     if (pClassDef.source_file_idx_.IsValid()) {
   1588       fileName = pDexFile->StringDataByIdx(pClassDef.source_file_idx_);
   1589     } else {
   1590       fileName = "unknown";
   1591     }
   1592     fprintf(gOutFile, "  source_file_idx   : %d (%s)\n\n",
   1593             pClassDef.source_file_idx_.index_, fileName);
   1594   } else if (gOptions.outputFormat == OUTPUT_XML) {
   1595     fprintf(gOutFile, "</class>\n");
   1596   }
   1597 
   1598   free(accessStr);
   1599 }
   1600 
   1601 static void dumpMethodHandle(const DexFile* pDexFile, u4 idx) {
   1602   const DexFile::MethodHandleItem& mh = pDexFile->GetMethodHandle(idx);
   1603   const char* type = nullptr;
   1604   bool is_instance = false;
   1605   bool is_invoke = false;
   1606   switch (static_cast<DexFile::MethodHandleType>(mh.method_handle_type_)) {
   1607     case DexFile::MethodHandleType::kStaticPut:
   1608       type = "put-static";
   1609       is_instance = false;
   1610       is_invoke = false;
   1611       break;
   1612     case DexFile::MethodHandleType::kStaticGet:
   1613       type = "get-static";
   1614       is_instance = false;
   1615       is_invoke = false;
   1616       break;
   1617     case DexFile::MethodHandleType::kInstancePut:
   1618       type = "put-instance";
   1619       is_instance = true;
   1620       is_invoke = false;
   1621       break;
   1622     case DexFile::MethodHandleType::kInstanceGet:
   1623       type = "get-instance";
   1624       is_instance = true;
   1625       is_invoke = false;
   1626       break;
   1627     case DexFile::MethodHandleType::kInvokeStatic:
   1628       type = "invoke-static";
   1629       is_instance = false;
   1630       is_invoke = true;
   1631       break;
   1632     case DexFile::MethodHandleType::kInvokeInstance:
   1633       type = "invoke-instance";
   1634       is_instance = true;
   1635       is_invoke = true;
   1636       break;
   1637     case DexFile::MethodHandleType::kInvokeConstructor:
   1638       type = "invoke-constructor";
   1639       is_instance = true;
   1640       is_invoke = true;
   1641       break;
   1642     case DexFile::MethodHandleType::kInvokeDirect:
   1643       type = "invoke-direct";
   1644       is_instance = true;
   1645       is_invoke = true;
   1646       break;
   1647     case DexFile::MethodHandleType::kInvokeInterface:
   1648       type = "invoke-interface";
   1649       is_instance = true;
   1650       is_invoke = true;
   1651       break;
   1652   }
   1653 
   1654   const char* declaring_class;
   1655   const char* member;
   1656   std::string member_type;
   1657   if (type != nullptr) {
   1658     if (is_invoke) {
   1659       const DexFile::MethodId& method_id = pDexFile->GetMethodId(mh.field_or_method_idx_);
   1660       declaring_class = pDexFile->GetMethodDeclaringClassDescriptor(method_id);
   1661       member = pDexFile->GetMethodName(method_id);
   1662       member_type = pDexFile->GetMethodSignature(method_id).ToString();
   1663     } else {
   1664       const DexFile::FieldId& field_id = pDexFile->GetFieldId(mh.field_or_method_idx_);
   1665       declaring_class = pDexFile->GetFieldDeclaringClassDescriptor(field_id);
   1666       member = pDexFile->GetFieldName(field_id);
   1667       member_type = pDexFile->GetFieldTypeDescriptor(field_id);
   1668     }
   1669     if (is_instance) {
   1670       member_type = android::base::StringPrintf("(%s%s", declaring_class, member_type.c_str() + 1);
   1671     }
   1672   } else {
   1673     type = "?";
   1674     declaring_class = "?";
   1675     member = "?";
   1676     member_type = "?";
   1677   }
   1678 
   1679   if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1680     fprintf(gOutFile, "Method handle #%u:\n", idx);
   1681     fprintf(gOutFile, "  type        : %s\n", type);
   1682     fprintf(gOutFile, "  target      : %s %s\n", declaring_class, member);
   1683     fprintf(gOutFile, "  target_type : %s\n", member_type.c_str());
   1684   } else {
   1685     fprintf(gOutFile, "<method_handle index=\"%u\"\n", idx);
   1686     fprintf(gOutFile, " type=\"%s\"\n", type);
   1687     fprintf(gOutFile, " target_class=\"%s\"\n", declaring_class);
   1688     fprintf(gOutFile, " target_member=\"%s\"\n", member);
   1689     fprintf(gOutFile, " target_member_type=");
   1690     dumpEscapedString(member_type.c_str());
   1691     fprintf(gOutFile, "\n>\n</method_handle>\n");
   1692   }
   1693 }
   1694 
   1695 static void dumpCallSite(const DexFile* pDexFile, u4 idx) {
   1696   const DexFile::CallSiteIdItem& call_site_id = pDexFile->GetCallSiteId(idx);
   1697   CallSiteArrayValueIterator it(*pDexFile, call_site_id);
   1698   if (it.Size() < 3) {
   1699     LOG(ERROR) << "ERROR: Call site " << idx << " has too few values.";
   1700     return;
   1701   }
   1702 
   1703   uint32_t method_handle_idx = static_cast<uint32_t>(it.GetJavaValue().i);
   1704   it.Next();
   1705   dex::StringIndex method_name_idx = static_cast<dex::StringIndex>(it.GetJavaValue().i);
   1706   const char* method_name = pDexFile->StringDataByIdx(method_name_idx);
   1707   it.Next();
   1708   uint32_t method_type_idx = static_cast<uint32_t>(it.GetJavaValue().i);
   1709   const DexFile::ProtoId& method_type_id = pDexFile->GetProtoId(method_type_idx);
   1710   std::string method_type = pDexFile->GetProtoSignature(method_type_id).ToString();
   1711   it.Next();
   1712 
   1713   if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1714     fprintf(gOutFile, "Call site #%u: // offset %u\n", idx, call_site_id.data_off_);
   1715     fprintf(gOutFile, "  link_argument[0] : %u (MethodHandle)\n", method_handle_idx);
   1716     fprintf(gOutFile, "  link_argument[1] : %s (String)\n", method_name);
   1717     fprintf(gOutFile, "  link_argument[2] : %s (MethodType)\n", method_type.c_str());
   1718   } else {
   1719     fprintf(gOutFile, "<call_site index=\"%u\" offset=\"%u\">\n", idx, call_site_id.data_off_);
   1720     fprintf(gOutFile,
   1721             "<link_argument index=\"0\" type=\"MethodHandle\" value=\"%u\"/>\n",
   1722             method_handle_idx);
   1723     fprintf(gOutFile,
   1724             "<link_argument index=\"1\" type=\"String\" values=\"%s\"/>\n",
   1725             method_name);
   1726     fprintf(gOutFile,
   1727             "<link_argument index=\"2\" type=\"MethodType\" value=\"%s\"/>\n",
   1728             method_type.c_str());
   1729   }
   1730 
   1731   size_t argument = 3;
   1732   while (it.HasNext()) {
   1733     const char* type;
   1734     std::string value;
   1735     switch (it.GetValueType()) {
   1736       case EncodedArrayValueIterator::ValueType::kByte:
   1737         type = "byte";
   1738         value = android::base::StringPrintf("%u", it.GetJavaValue().b);
   1739         break;
   1740       case EncodedArrayValueIterator::ValueType::kShort:
   1741         type = "short";
   1742         value = android::base::StringPrintf("%d", it.GetJavaValue().s);
   1743         break;
   1744       case EncodedArrayValueIterator::ValueType::kChar:
   1745         type = "char";
   1746         value = android::base::StringPrintf("%u", it.GetJavaValue().c);
   1747         break;
   1748       case EncodedArrayValueIterator::ValueType::kInt:
   1749         type = "int";
   1750         value = android::base::StringPrintf("%d", it.GetJavaValue().i);
   1751         break;
   1752       case EncodedArrayValueIterator::ValueType::kLong:
   1753         type = "long";
   1754         value = android::base::StringPrintf("%" PRId64, it.GetJavaValue().j);
   1755         break;
   1756       case EncodedArrayValueIterator::ValueType::kFloat:
   1757         type = "float";
   1758         value = android::base::StringPrintf("%g", it.GetJavaValue().f);
   1759         break;
   1760       case EncodedArrayValueIterator::ValueType::kDouble:
   1761         type = "double";
   1762         value = android::base::StringPrintf("%g", it.GetJavaValue().d);
   1763         break;
   1764       case EncodedArrayValueIterator::ValueType::kMethodType: {
   1765         type = "MethodType";
   1766         uint32_t proto_idx = static_cast<uint32_t>(it.GetJavaValue().i);
   1767         const DexFile::ProtoId& proto_id = pDexFile->GetProtoId(proto_idx);
   1768         value = pDexFile->GetProtoSignature(proto_id).ToString();
   1769         break;
   1770       }
   1771       case EncodedArrayValueIterator::ValueType::kMethodHandle:
   1772         type = "MethodHandle";
   1773         value = android::base::StringPrintf("%d", it.GetJavaValue().i);
   1774         break;
   1775       case EncodedArrayValueIterator::ValueType::kString: {
   1776         type = "String";
   1777         dex::StringIndex string_idx = static_cast<dex::StringIndex>(it.GetJavaValue().i);
   1778         value = pDexFile->StringDataByIdx(string_idx);
   1779         break;
   1780       }
   1781       case EncodedArrayValueIterator::ValueType::kType: {
   1782         type = "Class";
   1783         dex::TypeIndex type_idx = static_cast<dex::TypeIndex>(it.GetJavaValue().i);
   1784         const DexFile::ClassDef* class_def = pDexFile->FindClassDef(type_idx);
   1785         value = pDexFile->GetClassDescriptor(*class_def);
   1786         value = descriptorClassToDot(value.c_str()).get();
   1787         break;
   1788       }
   1789       case EncodedArrayValueIterator::ValueType::kField:
   1790       case EncodedArrayValueIterator::ValueType::kMethod:
   1791       case EncodedArrayValueIterator::ValueType::kEnum:
   1792       case EncodedArrayValueIterator::ValueType::kArray:
   1793       case EncodedArrayValueIterator::ValueType::kAnnotation:
   1794         // Unreachable based on current EncodedArrayValueIterator::Next().
   1795         UNIMPLEMENTED(FATAL) << " type " << it.GetValueType();
   1796         UNREACHABLE();
   1797       case EncodedArrayValueIterator::ValueType::kNull:
   1798         type = "Null";
   1799         value = "null";
   1800         break;
   1801       case EncodedArrayValueIterator::ValueType::kBoolean:
   1802         type = "boolean";
   1803         value = it.GetJavaValue().z ? "true" : "false";
   1804         break;
   1805     }
   1806 
   1807     if (gOptions.outputFormat == OUTPUT_PLAIN) {
   1808       fprintf(gOutFile, "  link_argument[%zu] : %s (%s)\n", argument, value.c_str(), type);
   1809     } else {
   1810       fprintf(gOutFile, "<link_argument index=\"%zu\" type=\"%s\" value=", argument, type);
   1811       dumpEscapedString(value.c_str());
   1812       fprintf(gOutFile, "/>\n");
   1813     }
   1814 
   1815     it.Next();
   1816     argument++;
   1817   }
   1818 
   1819   if (gOptions.outputFormat == OUTPUT_XML) {
   1820     fprintf(gOutFile, "</call_site>\n");
   1821   }
   1822 }
   1823 
   1824 /*
   1825  * Dumps the requested sections of the file.
   1826  */
   1827 static void processDexFile(const char* fileName,
   1828                            const DexFile* pDexFile, size_t i, size_t n) {
   1829   if (gOptions.verbose) {
   1830     fputs("Opened '", gOutFile);
   1831     fputs(fileName, gOutFile);
   1832     if (n > 1) {
   1833       fprintf(gOutFile, ":%s", DexFileLoader::GetMultiDexClassesDexName(i).c_str());
   1834     }
   1835     fprintf(gOutFile, "', DEX version '%.3s'\n", pDexFile->GetHeader().magic_ + 4);
   1836   }
   1837 
   1838   // Headers.
   1839   if (gOptions.showFileHeaders) {
   1840     dumpFileHeader(pDexFile);
   1841   }
   1842 
   1843   // Open XML context.
   1844   if (gOptions.outputFormat == OUTPUT_XML) {
   1845     fprintf(gOutFile, "<api>\n");
   1846   }
   1847 
   1848   // Iterate over all classes.
   1849   char* package = nullptr;
   1850   const u4 classDefsSize = pDexFile->GetHeader().class_defs_size_;
   1851   for (u4 i = 0; i < classDefsSize; i++) {
   1852     dumpClass(pDexFile, i, &package);
   1853   }  // for
   1854 
   1855   // Iterate over all method handles.
   1856   for (u4 i = 0; i < pDexFile->NumMethodHandles(); ++i) {
   1857     dumpMethodHandle(pDexFile, i);
   1858   }  // for
   1859 
   1860   // Iterate over all call site ids.
   1861   for (u4 i = 0; i < pDexFile->NumCallSiteIds(); ++i) {
   1862     dumpCallSite(pDexFile, i);
   1863   }  // for
   1864 
   1865   // Free the last package allocated.
   1866   if (package != nullptr) {
   1867     fprintf(gOutFile, "</package>\n");
   1868     free(package);
   1869   }
   1870 
   1871   // Close XML context.
   1872   if (gOptions.outputFormat == OUTPUT_XML) {
   1873     fprintf(gOutFile, "</api>\n");
   1874   }
   1875 }
   1876 
   1877 /*
   1878  * Processes a single file (either direct .dex or indirect .zip/.jar/.apk).
   1879  */
   1880 int processFile(const char* fileName) {
   1881   if (gOptions.verbose) {
   1882     fprintf(gOutFile, "Processing '%s'...\n", fileName);
   1883   }
   1884 
   1885   const bool kVerifyChecksum = !gOptions.ignoreBadChecksum;
   1886   const bool kVerify = !gOptions.disableVerifier;
   1887   std::string content;
   1888   // If the file is not a .dex file, the function tries .zip/.jar/.apk files,
   1889   // all of which are Zip archives with "classes.dex" inside.
   1890   // TODO: add an api to android::base to read a std::vector<uint8_t>.
   1891   if (!android::base::ReadFileToString(fileName, &content)) {
   1892     LOG(ERROR) << "ReadFileToString failed";
   1893     return -1;
   1894   }
   1895   const DexFileLoader dex_file_loader;
   1896   std::string error_msg;
   1897   std::vector<std::unique_ptr<const DexFile>> dex_files;
   1898   if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()),
   1899                                content.size(),
   1900                                fileName,
   1901                                kVerify,
   1902                                kVerifyChecksum,
   1903                                &error_msg,
   1904                                &dex_files)) {
   1905     // Display returned error message to user. Note that this error behavior
   1906     // differs from the error messages shown by the original Dalvik dexdump.
   1907     LOG(ERROR) << error_msg;
   1908     return -1;
   1909   }
   1910 
   1911   // Success. Either report checksum verification or process
   1912   // all dex files found in given file.
   1913   if (gOptions.checksumOnly) {
   1914     fprintf(gOutFile, "Checksum verified\n");
   1915   } else {
   1916     for (size_t i = 0, n = dex_files.size(); i < n; i++) {
   1917       processDexFile(fileName, dex_files[i].get(), i, n);
   1918     }
   1919   }
   1920   return 0;
   1921 }
   1922 
   1923 }  // namespace art
   1924