Home | History | Annotate | Download | only in oatdump
      1 /*
      2  * Copyright (C) 2011 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 #include <stdio.h>
     18 #include <stdlib.h>
     19 
     20 #include <fstream>
     21 #include <iostream>
     22 #include <map>
     23 #include <set>
     24 #include <string>
     25 #include <unordered_map>
     26 #include <unordered_set>
     27 #include <vector>
     28 
     29 #include "android-base/stringprintf.h"
     30 #include "android-base/strings.h"
     31 
     32 #include "arch/instruction_set_features.h"
     33 #include "art_field-inl.h"
     34 #include "art_method-inl.h"
     35 #include "base/stl_util.h"
     36 #include "base/unix_file/fd_file.h"
     37 #include "class_linker.h"
     38 #include "class_linker-inl.h"
     39 #include "debug/elf_debug_writer.h"
     40 #include "debug/method_debug_info.h"
     41 #include "dex_file-inl.h"
     42 #include "dex_instruction-inl.h"
     43 #include "disassembler.h"
     44 #include "elf_builder.h"
     45 #include "gc/space/image_space.h"
     46 #include "gc/space/large_object_space.h"
     47 #include "gc/space/space-inl.h"
     48 #include "image-inl.h"
     49 #include "imtable-inl.h"
     50 #include "indenter.h"
     51 #include "interpreter/unstarted_runtime.h"
     52 #include "linker/buffered_output_stream.h"
     53 #include "linker/file_output_stream.h"
     54 #include "mirror/array-inl.h"
     55 #include "mirror/class-inl.h"
     56 #include "mirror/dex_cache-inl.h"
     57 #include "mirror/object-inl.h"
     58 #include "mirror/object_array-inl.h"
     59 #include "oat.h"
     60 #include "oat_file-inl.h"
     61 #include "oat_file_manager.h"
     62 #include "os.h"
     63 #include "safe_map.h"
     64 #include "scoped_thread_state_change-inl.h"
     65 #include "ScopedLocalRef.h"
     66 #include "stack_map.h"
     67 #include "string_reference.h"
     68 #include "thread_list.h"
     69 #include "type_lookup_table.h"
     70 #include "vdex_file.h"
     71 #include "verifier/method_verifier.h"
     72 #include "verifier/verifier_deps.h"
     73 #include "well_known_classes.h"
     74 
     75 #include <sys/stat.h>
     76 #include "cmdline.h"
     77 
     78 namespace art {
     79 
     80 using android::base::StringPrintf;
     81 
     82 const char* image_methods_descriptions_[] = {
     83   "kResolutionMethod",
     84   "kImtConflictMethod",
     85   "kImtUnimplementedMethod",
     86   "kSaveAllCalleeSavesMethod",
     87   "kSaveRefsOnlyMethod",
     88   "kSaveRefsAndArgsMethod",
     89   "kSaveEverythingMethod",
     90 };
     91 
     92 const char* image_roots_descriptions_[] = {
     93   "kDexCaches",
     94   "kClassRoots",
     95   "kClassLoader",
     96 };
     97 
     98 // Map is so that we don't allocate multiple dex files for the same OatDexFile.
     99 static std::map<const OatFile::OatDexFile*,
    100                 std::unique_ptr<const DexFile>> opened_dex_files;
    101 
    102 const DexFile* OpenDexFile(const OatFile::OatDexFile* oat_dex_file, std::string* error_msg) {
    103   DCHECK(oat_dex_file != nullptr);
    104   auto it = opened_dex_files.find(oat_dex_file);
    105   if (it != opened_dex_files.end()) {
    106     return it->second.get();
    107   }
    108   const DexFile* ret = oat_dex_file->OpenDexFile(error_msg).release();
    109   opened_dex_files.emplace(oat_dex_file, std::unique_ptr<const DexFile>(ret));
    110   return ret;
    111 }
    112 
    113 template <typename ElfTypes>
    114 class OatSymbolizer FINAL {
    115  public:
    116   OatSymbolizer(const OatFile* oat_file, const std::string& output_name, bool no_bits) :
    117       oat_file_(oat_file),
    118       builder_(nullptr),
    119       output_name_(output_name.empty() ? "symbolized.oat" : output_name),
    120       no_bits_(no_bits) {
    121   }
    122 
    123   bool Symbolize() {
    124     const InstructionSet isa = oat_file_->GetOatHeader().GetInstructionSet();
    125     std::unique_ptr<const InstructionSetFeatures> features = InstructionSetFeatures::FromBitmap(
    126         isa, oat_file_->GetOatHeader().GetInstructionSetFeaturesBitmap());
    127 
    128     File* elf_file = OS::CreateEmptyFile(output_name_.c_str());
    129     std::unique_ptr<BufferedOutputStream> output_stream(
    130         MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file)));
    131     builder_.reset(new ElfBuilder<ElfTypes>(isa, features.get(), output_stream.get()));
    132 
    133     builder_->Start();
    134 
    135     auto* rodata = builder_->GetRoData();
    136     auto* text = builder_->GetText();
    137     auto* bss = builder_->GetBss();
    138 
    139     const uint8_t* rodata_begin = oat_file_->Begin();
    140     const size_t rodata_size = oat_file_->GetOatHeader().GetExecutableOffset();
    141     if (no_bits_) {
    142       rodata->WriteNoBitsSection(rodata_size);
    143     } else {
    144       rodata->Start();
    145       rodata->WriteFully(rodata_begin, rodata_size);
    146       rodata->End();
    147     }
    148 
    149     const uint8_t* text_begin = oat_file_->Begin() + rodata_size;
    150     const size_t text_size = oat_file_->End() - text_begin;
    151     if (no_bits_) {
    152       text->WriteNoBitsSection(text_size);
    153     } else {
    154       text->Start();
    155       text->WriteFully(text_begin, text_size);
    156       text->End();
    157     }
    158 
    159     if (oat_file_->BssSize() != 0) {
    160       bss->WriteNoBitsSection(oat_file_->BssSize());
    161     }
    162 
    163     if (isa == kMips || isa == kMips64) {
    164       builder_->WriteMIPSabiflagsSection();
    165     }
    166     builder_->PrepareDynamicSection(elf_file->GetPath(),
    167                                     rodata_size,
    168                                     text_size,
    169                                     oat_file_->BssSize(),
    170                                     oat_file_->BssRootsOffset());
    171     builder_->WriteDynamicSection();
    172 
    173     Walk();
    174     for (const auto& trampoline : debug::MakeTrampolineInfos(oat_file_->GetOatHeader())) {
    175       method_debug_infos_.push_back(trampoline);
    176     }
    177 
    178     debug::WriteDebugInfo(builder_.get(),
    179                           ArrayRef<const debug::MethodDebugInfo>(method_debug_infos_),
    180                           dwarf::DW_DEBUG_FRAME_FORMAT,
    181                           true /* write_oat_patches */);
    182 
    183     builder_->End();
    184 
    185     return builder_->Good();
    186   }
    187 
    188   void Walk() {
    189     std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file_->GetOatDexFiles();
    190     for (size_t i = 0; i < oat_dex_files.size(); i++) {
    191       const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
    192       CHECK(oat_dex_file != nullptr);
    193       WalkOatDexFile(oat_dex_file);
    194     }
    195   }
    196 
    197   void WalkOatDexFile(const OatFile::OatDexFile* oat_dex_file) {
    198     std::string error_msg;
    199     const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
    200     if (dex_file == nullptr) {
    201       return;
    202     }
    203     for (size_t class_def_index = 0;
    204         class_def_index < dex_file->NumClassDefs();
    205         class_def_index++) {
    206       const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
    207       OatClassType type = oat_class.GetType();
    208       switch (type) {
    209         case kOatClassAllCompiled:
    210         case kOatClassSomeCompiled:
    211           WalkOatClass(oat_class, *dex_file, class_def_index);
    212           break;
    213 
    214         case kOatClassNoneCompiled:
    215         case kOatClassMax:
    216           // Ignore.
    217           break;
    218       }
    219     }
    220   }
    221 
    222   void WalkOatClass(const OatFile::OatClass& oat_class,
    223                     const DexFile& dex_file,
    224                     uint32_t class_def_index) {
    225     const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
    226     const uint8_t* class_data = dex_file.GetClassData(class_def);
    227     if (class_data == nullptr) {  // empty class such as a marker interface?
    228       return;
    229     }
    230     // Note: even if this is an interface or a native class, we still have to walk it, as there
    231     //       might be a static initializer.
    232     ClassDataItemIterator it(dex_file, class_data);
    233     uint32_t class_method_idx = 0;
    234     for (; it.HasNextStaticField(); it.Next()) { /* skip */ }
    235     for (; it.HasNextInstanceField(); it.Next()) { /* skip */ }
    236     for (; it.HasNextDirectMethod() || it.HasNextVirtualMethod(); it.Next()) {
    237       WalkOatMethod(oat_class.GetOatMethod(class_method_idx++),
    238                     dex_file,
    239                     class_def_index,
    240                     it.GetMemberIndex(),
    241                     it.GetMethodCodeItem(),
    242                     it.GetMethodAccessFlags());
    243     }
    244     DCHECK(!it.HasNext());
    245   }
    246 
    247   void WalkOatMethod(const OatFile::OatMethod& oat_method,
    248                      const DexFile& dex_file,
    249                      uint32_t class_def_index,
    250                      uint32_t dex_method_index,
    251                      const DexFile::CodeItem* code_item,
    252                      uint32_t method_access_flags) {
    253     if ((method_access_flags & kAccAbstract) != 0) {
    254       // Abstract method, no code.
    255       return;
    256     }
    257     const OatHeader& oat_header = oat_file_->GetOatHeader();
    258     const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
    259     if (method_header == nullptr || method_header->GetCodeSize() == 0) {
    260       // No code.
    261       return;
    262     }
    263 
    264     uint32_t entry_point = oat_method.GetCodeOffset() - oat_header.GetExecutableOffset();
    265     // Clear Thumb2 bit.
    266     const void* code_address = EntryPointToCodePointer(reinterpret_cast<void*>(entry_point));
    267 
    268     debug::MethodDebugInfo info = debug::MethodDebugInfo();
    269     info.trampoline_name = nullptr;
    270     info.dex_file = &dex_file;
    271     info.class_def_index = class_def_index;
    272     info.dex_method_index = dex_method_index;
    273     info.access_flags = method_access_flags;
    274     info.code_item = code_item;
    275     info.isa = oat_header.GetInstructionSet();
    276     info.deduped = !seen_offsets_.insert(oat_method.GetCodeOffset()).second;
    277     info.is_native_debuggable = oat_header.IsNativeDebuggable();
    278     info.is_optimized = method_header->IsOptimized();
    279     info.is_code_address_text_relative = true;
    280     info.code_address = reinterpret_cast<uintptr_t>(code_address);
    281     info.code_size = method_header->GetCodeSize();
    282     info.frame_size_in_bytes = method_header->GetFrameSizeInBytes();
    283     info.code_info = info.is_optimized ? method_header->GetOptimizedCodeInfoPtr() : nullptr;
    284     info.cfi = ArrayRef<uint8_t>();
    285     method_debug_infos_.push_back(info);
    286   }
    287 
    288  private:
    289   const OatFile* oat_file_;
    290   std::unique_ptr<ElfBuilder<ElfTypes> > builder_;
    291   std::vector<debug::MethodDebugInfo> method_debug_infos_;
    292   std::unordered_set<uint32_t> seen_offsets_;
    293   const std::string output_name_;
    294   bool no_bits_;
    295 };
    296 
    297 class OatDumperOptions {
    298  public:
    299   OatDumperOptions(bool dump_vmap,
    300                    bool dump_code_info_stack_maps,
    301                    bool disassemble_code,
    302                    bool absolute_addresses,
    303                    const char* class_filter,
    304                    const char* method_filter,
    305                    bool list_classes,
    306                    bool list_methods,
    307                    bool dump_header_only,
    308                    const char* export_dex_location,
    309                    const char* app_image,
    310                    const char* app_oat,
    311                    uint32_t addr2instr)
    312     : dump_vmap_(dump_vmap),
    313       dump_code_info_stack_maps_(dump_code_info_stack_maps),
    314       disassemble_code_(disassemble_code),
    315       absolute_addresses_(absolute_addresses),
    316       class_filter_(class_filter),
    317       method_filter_(method_filter),
    318       list_classes_(list_classes),
    319       list_methods_(list_methods),
    320       dump_header_only_(dump_header_only),
    321       export_dex_location_(export_dex_location),
    322       app_image_(app_image),
    323       app_oat_(app_oat),
    324       addr2instr_(addr2instr),
    325       class_loader_(nullptr) {}
    326 
    327   const bool dump_vmap_;
    328   const bool dump_code_info_stack_maps_;
    329   const bool disassemble_code_;
    330   const bool absolute_addresses_;
    331   const char* const class_filter_;
    332   const char* const method_filter_;
    333   const bool list_classes_;
    334   const bool list_methods_;
    335   const bool dump_header_only_;
    336   const char* const export_dex_location_;
    337   const char* const app_image_;
    338   const char* const app_oat_;
    339   uint32_t addr2instr_;
    340   Handle<mirror::ClassLoader>* class_loader_;
    341 };
    342 
    343 class OatDumper {
    344  public:
    345   OatDumper(const OatFile& oat_file, const OatDumperOptions& options)
    346     : oat_file_(oat_file),
    347       oat_dex_files_(oat_file.GetOatDexFiles()),
    348       options_(options),
    349       resolved_addr2instr_(0),
    350       instruction_set_(oat_file_.GetOatHeader().GetInstructionSet()),
    351       disassembler_(Disassembler::Create(instruction_set_,
    352                                          new DisassemblerOptions(
    353                                              options_.absolute_addresses_,
    354                                              oat_file.Begin(),
    355                                              oat_file.End(),
    356                                              true /* can_read_literals_ */,
    357                                              Is64BitInstructionSet(instruction_set_)
    358                                                  ? &Thread::DumpThreadOffset<PointerSize::k64>
    359                                                  : &Thread::DumpThreadOffset<PointerSize::k32>))) {
    360     CHECK(options_.class_loader_ != nullptr);
    361     CHECK(options_.class_filter_ != nullptr);
    362     CHECK(options_.method_filter_ != nullptr);
    363     AddAllOffsets();
    364   }
    365 
    366   ~OatDumper() {
    367     delete disassembler_;
    368   }
    369 
    370   InstructionSet GetInstructionSet() {
    371     return instruction_set_;
    372   }
    373 
    374   bool Dump(std::ostream& os) {
    375     bool success = true;
    376     const OatHeader& oat_header = oat_file_.GetOatHeader();
    377 
    378     os << "MAGIC:\n";
    379     os << oat_header.GetMagic() << "\n\n";
    380 
    381     os << "LOCATION:\n";
    382     os << oat_file_.GetLocation() << "\n\n";
    383 
    384     os << "CHECKSUM:\n";
    385     os << StringPrintf("0x%08x\n\n", oat_header.GetChecksum());
    386 
    387     os << "INSTRUCTION SET:\n";
    388     os << oat_header.GetInstructionSet() << "\n\n";
    389 
    390     {
    391       std::unique_ptr<const InstructionSetFeatures> features(
    392           InstructionSetFeatures::FromBitmap(oat_header.GetInstructionSet(),
    393                                              oat_header.GetInstructionSetFeaturesBitmap()));
    394       os << "INSTRUCTION SET FEATURES:\n";
    395       os << features->GetFeatureString() << "\n\n";
    396     }
    397 
    398     os << "DEX FILE COUNT:\n";
    399     os << oat_header.GetDexFileCount() << "\n\n";
    400 
    401 #define DUMP_OAT_HEADER_OFFSET(label, offset) \
    402     os << label " OFFSET:\n"; \
    403     os << StringPrintf("0x%08x", oat_header.offset()); \
    404     if (oat_header.offset() != 0 && options_.absolute_addresses_) { \
    405       os << StringPrintf(" (%p)", oat_file_.Begin() + oat_header.offset()); \
    406     } \
    407     os << StringPrintf("\n\n");
    408 
    409     DUMP_OAT_HEADER_OFFSET("EXECUTABLE", GetExecutableOffset);
    410     DUMP_OAT_HEADER_OFFSET("INTERPRETER TO INTERPRETER BRIDGE",
    411                            GetInterpreterToInterpreterBridgeOffset);
    412     DUMP_OAT_HEADER_OFFSET("INTERPRETER TO COMPILED CODE BRIDGE",
    413                            GetInterpreterToCompiledCodeBridgeOffset);
    414     DUMP_OAT_HEADER_OFFSET("JNI DLSYM LOOKUP",
    415                            GetJniDlsymLookupOffset);
    416     DUMP_OAT_HEADER_OFFSET("QUICK GENERIC JNI TRAMPOLINE",
    417                            GetQuickGenericJniTrampolineOffset);
    418     DUMP_OAT_HEADER_OFFSET("QUICK IMT CONFLICT TRAMPOLINE",
    419                            GetQuickImtConflictTrampolineOffset);
    420     DUMP_OAT_HEADER_OFFSET("QUICK RESOLUTION TRAMPOLINE",
    421                            GetQuickResolutionTrampolineOffset);
    422     DUMP_OAT_HEADER_OFFSET("QUICK TO INTERPRETER BRIDGE",
    423                            GetQuickToInterpreterBridgeOffset);
    424 #undef DUMP_OAT_HEADER_OFFSET
    425 
    426     os << "IMAGE PATCH DELTA:\n";
    427     os << StringPrintf("%d (0x%08x)\n\n",
    428                        oat_header.GetImagePatchDelta(),
    429                        oat_header.GetImagePatchDelta());
    430 
    431     os << "IMAGE FILE LOCATION OAT CHECKSUM:\n";
    432     os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatChecksum());
    433 
    434     os << "IMAGE FILE LOCATION OAT BEGIN:\n";
    435     os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatDataBegin());
    436 
    437     // Print the key-value store.
    438     {
    439       os << "KEY VALUE STORE:\n";
    440       size_t index = 0;
    441       const char* key;
    442       const char* value;
    443       while (oat_header.GetStoreKeyValuePairByIndex(index, &key, &value)) {
    444         os << key << " = " << value << "\n";
    445         index++;
    446       }
    447       os << "\n";
    448     }
    449 
    450     if (options_.absolute_addresses_) {
    451       os << "BEGIN:\n";
    452       os << reinterpret_cast<const void*>(oat_file_.Begin()) << "\n\n";
    453 
    454       os << "END:\n";
    455       os << reinterpret_cast<const void*>(oat_file_.End()) << "\n\n";
    456     }
    457 
    458     os << "SIZE:\n";
    459     os << oat_file_.Size() << "\n\n";
    460 
    461     os << std::flush;
    462 
    463     // If set, adjust relative address to be searched
    464     if (options_.addr2instr_ != 0) {
    465       resolved_addr2instr_ = options_.addr2instr_ + oat_header.GetExecutableOffset();
    466       os << "SEARCH ADDRESS (executable offset + input):\n";
    467       os << StringPrintf("0x%08x\n\n", resolved_addr2instr_);
    468     }
    469 
    470     // Dumping the dex file overview is compact enough to do even if header only.
    471     DexFileData cumulative;
    472     for (size_t i = 0; i < oat_dex_files_.size(); i++) {
    473       const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
    474       CHECK(oat_dex_file != nullptr);
    475       std::string error_msg;
    476       const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
    477       if (dex_file == nullptr) {
    478         os << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation() << "': "
    479            << error_msg;
    480         continue;
    481       }
    482       DexFileData data(*dex_file);
    483       os << "Dex file data for " << dex_file->GetLocation() << "\n";
    484       data.Dump(os);
    485       os << "\n";
    486       cumulative.Add(data);
    487     }
    488     os << "Cumulative dex file data\n";
    489     cumulative.Dump(os);
    490     os << "\n";
    491 
    492     if (!options_.dump_header_only_) {
    493       VariableIndentationOutputStream vios(&os);
    494       VdexFile::Header vdex_header = oat_file_.GetVdexFile()->GetHeader();
    495       if (vdex_header.IsValid()) {
    496         std::string error_msg;
    497         std::vector<const DexFile*> dex_files;
    498         for (size_t i = 0; i < oat_dex_files_.size(); i++) {
    499           const DexFile* dex_file = OpenDexFile(oat_dex_files_[i], &error_msg);
    500           if (dex_file == nullptr) {
    501             os << "Error opening dex file: " << error_msg << std::endl;
    502             return false;
    503           }
    504           dex_files.push_back(dex_file);
    505         }
    506         verifier::VerifierDeps deps(dex_files, oat_file_.GetVdexFile()->GetVerifierDepsData());
    507         deps.Dump(&vios);
    508       } else {
    509         os << "UNRECOGNIZED vdex file, magic "
    510            << vdex_header.GetMagic()
    511            << ", version "
    512            << vdex_header.GetVersion()
    513            << "\n";
    514       }
    515       for (size_t i = 0; i < oat_dex_files_.size(); i++) {
    516         const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
    517         CHECK(oat_dex_file != nullptr);
    518 
    519         // If file export selected skip file analysis
    520         if (options_.export_dex_location_) {
    521           if (!ExportDexFile(os, *oat_dex_file)) {
    522             success = false;
    523           }
    524         } else {
    525           if (!DumpOatDexFile(os, *oat_dex_file)) {
    526             success = false;
    527           }
    528         }
    529       }
    530     }
    531 
    532     {
    533       os << "OAT FILE STATS:\n";
    534       VariableIndentationOutputStream vios(&os);
    535       stats_.Dump(vios);
    536     }
    537 
    538     os << std::flush;
    539     return success;
    540   }
    541 
    542   size_t ComputeSize(const void* oat_data) {
    543     if (reinterpret_cast<const uint8_t*>(oat_data) < oat_file_.Begin() ||
    544         reinterpret_cast<const uint8_t*>(oat_data) > oat_file_.End()) {
    545       return 0;  // Address not in oat file
    546     }
    547     uintptr_t begin_offset = reinterpret_cast<uintptr_t>(oat_data) -
    548                              reinterpret_cast<uintptr_t>(oat_file_.Begin());
    549     auto it = offsets_.upper_bound(begin_offset);
    550     CHECK(it != offsets_.end());
    551     uintptr_t end_offset = *it;
    552     return end_offset - begin_offset;
    553   }
    554 
    555   InstructionSet GetOatInstructionSet() {
    556     return oat_file_.GetOatHeader().GetInstructionSet();
    557   }
    558 
    559   const void* GetQuickOatCode(ArtMethod* m) REQUIRES_SHARED(Locks::mutator_lock_) {
    560     for (size_t i = 0; i < oat_dex_files_.size(); i++) {
    561       const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
    562       CHECK(oat_dex_file != nullptr);
    563       std::string error_msg;
    564       const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
    565       if (dex_file == nullptr) {
    566         LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation()
    567             << "': " << error_msg;
    568       } else {
    569         const char* descriptor = m->GetDeclaringClassDescriptor();
    570         const DexFile::ClassDef* class_def =
    571             OatDexFile::FindClassDef(*dex_file, descriptor, ComputeModifiedUtf8Hash(descriptor));
    572         if (class_def != nullptr) {
    573           uint16_t class_def_index = dex_file->GetIndexForClassDef(*class_def);
    574           const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
    575           size_t method_index = m->GetMethodIndex();
    576           return oat_class.GetOatMethod(method_index).GetQuickCode();
    577         }
    578       }
    579     }
    580     return nullptr;
    581   }
    582 
    583   struct Stats {
    584     enum ByteKind {
    585       kByteKindCode,
    586       kByteKindQuickMethodHeader,
    587       kByteKindCodeInfoLocationCatalog,
    588       kByteKindCodeInfoDexRegisterMap,
    589       kByteKindCodeInfoEncoding,
    590       kByteKindCodeInfoInvokeInfo,
    591       kByteKindCodeInfoStackMasks,
    592       kByteKindCodeInfoRegisterMasks,
    593       kByteKindStackMapNativePc,
    594       kByteKindStackMapDexPc,
    595       kByteKindStackMapDexRegisterMap,
    596       kByteKindStackMapInlineInfoIndex,
    597       kByteKindStackMapRegisterMaskIndex,
    598       kByteKindStackMapStackMaskIndex,
    599       kByteKindInlineInfoMethodIndexIdx,
    600       kByteKindInlineInfoDexPc,
    601       kByteKindInlineInfoExtraData,
    602       kByteKindInlineInfoDexRegisterMap,
    603       kByteKindInlineInfoIsLast,
    604       kByteKindCount,
    605       // Special ranges for std::accumulate convenience.
    606       kByteKindStackMapFirst = kByteKindStackMapNativePc,
    607       kByteKindStackMapLast = kByteKindStackMapStackMaskIndex,
    608       kByteKindInlineInfoFirst = kByteKindInlineInfoMethodIndexIdx,
    609       kByteKindInlineInfoLast = kByteKindInlineInfoIsLast,
    610     };
    611     int64_t bits[kByteKindCount] = {};
    612     // Since code has deduplication, seen tracks already seen pointers to avoid double counting
    613     // deduplicated code and tables.
    614     std::unordered_set<const void*> seen;
    615 
    616     // Returns true if it was newly added.
    617     bool AddBitsIfUnique(ByteKind kind, int64_t count, const void* address) {
    618       if (seen.insert(address).second == true) {
    619         // True means the address was not already in the set.
    620         AddBits(kind, count);
    621         return true;
    622       }
    623       return false;
    624     }
    625 
    626     void AddBits(ByteKind kind, int64_t count) {
    627       bits[kind] += count;
    628     }
    629 
    630     void Dump(VariableIndentationOutputStream& os) {
    631       const int64_t sum = std::accumulate(bits, bits + kByteKindCount, 0u);
    632       os.Stream() << "Dumping cumulative use of " << sum / kBitsPerByte << " accounted bytes\n";
    633       if (sum > 0) {
    634         Dump(os, "Code                            ", bits[kByteKindCode], sum);
    635         Dump(os, "QuickMethodHeader               ", bits[kByteKindQuickMethodHeader], sum);
    636         Dump(os, "CodeInfoEncoding                ", bits[kByteKindCodeInfoEncoding], sum);
    637         Dump(os, "CodeInfoLocationCatalog         ", bits[kByteKindCodeInfoLocationCatalog], sum);
    638         Dump(os, "CodeInfoDexRegisterMap          ", bits[kByteKindCodeInfoDexRegisterMap], sum);
    639         Dump(os, "CodeInfoStackMasks              ", bits[kByteKindCodeInfoStackMasks], sum);
    640         Dump(os, "CodeInfoRegisterMasks           ", bits[kByteKindCodeInfoRegisterMasks], sum);
    641         Dump(os, "CodeInfoInvokeInfo              ", bits[kByteKindCodeInfoInvokeInfo], sum);
    642         // Stack map section.
    643         const int64_t stack_map_bits = std::accumulate(bits + kByteKindStackMapFirst,
    644                                                        bits + kByteKindStackMapLast + 1,
    645                                                        0u);
    646         Dump(os, "CodeInfoStackMap                ", stack_map_bits, sum);
    647         {
    648           ScopedIndentation indent1(&os);
    649           Dump(os,
    650                "StackMapNativePc              ",
    651                bits[kByteKindStackMapNativePc],
    652                stack_map_bits,
    653                "stack map");
    654           Dump(os,
    655                "StackMapDexPcEncoding         ",
    656                bits[kByteKindStackMapDexPc],
    657                stack_map_bits,
    658                "stack map");
    659           Dump(os,
    660                "StackMapDexRegisterMap        ",
    661                bits[kByteKindStackMapDexRegisterMap],
    662                stack_map_bits,
    663                "stack map");
    664           Dump(os,
    665                "StackMapInlineInfoIndex       ",
    666                bits[kByteKindStackMapInlineInfoIndex],
    667                stack_map_bits,
    668                "stack map");
    669           Dump(os,
    670                "StackMapRegisterMaskIndex     ",
    671                bits[kByteKindStackMapRegisterMaskIndex],
    672                stack_map_bits,
    673                "stack map");
    674           Dump(os,
    675                "StackMapStackMaskIndex        ",
    676                bits[kByteKindStackMapStackMaskIndex],
    677                stack_map_bits,
    678                "stack map");
    679         }
    680         // Inline info section.
    681         const int64_t inline_info_bits = std::accumulate(bits + kByteKindInlineInfoFirst,
    682                                                          bits + kByteKindInlineInfoLast + 1,
    683                                                          0u);
    684         Dump(os, "CodeInfoInlineInfo              ", inline_info_bits, sum);
    685         {
    686           ScopedIndentation indent1(&os);
    687           Dump(os,
    688                "InlineInfoMethodIndexIdx      ",
    689                bits[kByteKindInlineInfoMethodIndexIdx],
    690                inline_info_bits,
    691                "inline info");
    692           Dump(os,
    693                "InlineInfoDexPc               ",
    694                bits[kByteKindStackMapDexPc],
    695                inline_info_bits,
    696                "inline info");
    697           Dump(os,
    698                "InlineInfoExtraData           ",
    699                bits[kByteKindInlineInfoExtraData],
    700                inline_info_bits,
    701                "inline info");
    702           Dump(os,
    703                "InlineInfoDexRegisterMap      ",
    704                bits[kByteKindInlineInfoDexRegisterMap],
    705                inline_info_bits,
    706                "inline info");
    707           Dump(os,
    708                "InlineInfoIsLast              ",
    709                bits[kByteKindInlineInfoIsLast],
    710                inline_info_bits,
    711                "inline info");
    712         }
    713       }
    714       os.Stream() << "\n" << std::flush;
    715     }
    716 
    717    private:
    718     void Dump(VariableIndentationOutputStream& os,
    719               const char* name,
    720               int64_t size,
    721               int64_t total,
    722               const char* sum_of = "total") {
    723       const double percent = (static_cast<double>(size) / static_cast<double>(total)) * 100;
    724       os.Stream() << StringPrintf("%s = %8" PRId64 " (%2.0f%% of %s)\n",
    725                                   name,
    726                                   size / kBitsPerByte,
    727                                   percent,
    728                                   sum_of);
    729     }
    730   };
    731 
    732  private:
    733   void AddAllOffsets() {
    734     // We don't know the length of the code for each method, but we need to know where to stop
    735     // when disassembling. What we do know is that a region of code will be followed by some other
    736     // region, so if we keep a sorted sequence of the start of each region, we can infer the length
    737     // of a piece of code by using upper_bound to find the start of the next region.
    738     for (size_t i = 0; i < oat_dex_files_.size(); i++) {
    739       const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
    740       CHECK(oat_dex_file != nullptr);
    741       std::string error_msg;
    742       const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
    743       if (dex_file == nullptr) {
    744         LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation()
    745             << "': " << error_msg;
    746         continue;
    747       }
    748       offsets_.insert(reinterpret_cast<uintptr_t>(&dex_file->GetHeader()));
    749       for (size_t class_def_index = 0;
    750            class_def_index < dex_file->NumClassDefs();
    751            class_def_index++) {
    752         const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
    753         const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
    754         const uint8_t* class_data = dex_file->GetClassData(class_def);
    755         if (class_data != nullptr) {
    756           ClassDataItemIterator it(*dex_file, class_data);
    757           SkipAllFields(it);
    758           uint32_t class_method_index = 0;
    759           while (it.HasNextDirectMethod()) {
    760             AddOffsets(oat_class.GetOatMethod(class_method_index++));
    761             it.Next();
    762           }
    763           while (it.HasNextVirtualMethod()) {
    764             AddOffsets(oat_class.GetOatMethod(class_method_index++));
    765             it.Next();
    766           }
    767         }
    768       }
    769     }
    770 
    771     // If the last thing in the file is code for a method, there won't be an offset for the "next"
    772     // thing. Instead of having a special case in the upper_bound code, let's just add an entry
    773     // for the end of the file.
    774     offsets_.insert(oat_file_.Size());
    775   }
    776 
    777   static uint32_t AlignCodeOffset(uint32_t maybe_thumb_offset) {
    778     return maybe_thumb_offset & ~0x1;  // TODO: Make this Thumb2 specific.
    779   }
    780 
    781   void AddOffsets(const OatFile::OatMethod& oat_method) {
    782     uint32_t code_offset = oat_method.GetCodeOffset();
    783     if (oat_file_.GetOatHeader().GetInstructionSet() == kThumb2) {
    784       code_offset &= ~0x1;
    785     }
    786     offsets_.insert(code_offset);
    787     offsets_.insert(oat_method.GetVmapTableOffset());
    788   }
    789 
    790   // Dex file data, may be for multiple different dex files.
    791   class DexFileData {
    792    public:
    793     DexFileData() {}
    794 
    795     explicit DexFileData(const DexFile& dex_file)
    796         : num_string_ids_(dex_file.NumStringIds()),
    797           num_method_ids_(dex_file.NumMethodIds()),
    798           num_field_ids_(dex_file.NumFieldIds()),
    799           num_type_ids_(dex_file.NumTypeIds()),
    800           num_class_defs_(dex_file.NumClassDefs()) {
    801       for (size_t class_def_index = 0; class_def_index < num_class_defs_; ++class_def_index) {
    802         const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
    803         WalkClass(dex_file, class_def);
    804       }
    805     }
    806 
    807     void Add(const DexFileData& other) {
    808       AddAll(unique_string_ids_from_code_, other.unique_string_ids_from_code_);
    809       num_string_ids_from_code_ += other.num_string_ids_from_code_;
    810       AddAll(dex_code_item_ptrs_, other.dex_code_item_ptrs_);
    811       dex_code_bytes_ += other.dex_code_bytes_;
    812       num_string_ids_ += other.num_string_ids_;
    813       num_method_ids_ += other.num_method_ids_;
    814       num_field_ids_ += other.num_field_ids_;
    815       num_type_ids_ += other.num_type_ids_;
    816       num_class_defs_ += other.num_class_defs_;
    817     }
    818 
    819     void Dump(std::ostream& os) {
    820       os << "Num string ids: " << num_string_ids_ << "\n";
    821       os << "Num method ids: " << num_method_ids_ << "\n";
    822       os << "Num field ids: " << num_field_ids_ << "\n";
    823       os << "Num type ids: " << num_type_ids_ << "\n";
    824       os << "Num class defs: " << num_class_defs_ << "\n";
    825       os << "Unique strings loaded from dex code: " << unique_string_ids_from_code_.size() << "\n";
    826       os << "Total strings loaded from dex code: " << num_string_ids_from_code_ << "\n";
    827       os << "Number of unique dex code items: " << dex_code_item_ptrs_.size() << "\n";
    828       os << "Total number of dex code bytes: " << dex_code_bytes_ << "\n";
    829     }
    830 
    831   private:
    832     // All of the elements from one container to another.
    833     template <typename Dest, typename Src>
    834     static void AddAll(Dest& dest, const Src& src) {
    835       dest.insert(src.begin(), src.end());
    836     }
    837 
    838     void WalkClass(const DexFile& dex_file, const DexFile::ClassDef& class_def) {
    839       const uint8_t* class_data = dex_file.GetClassData(class_def);
    840       if (class_data == nullptr) {  // empty class such as a marker interface?
    841         return;
    842       }
    843       ClassDataItemIterator it(dex_file, class_data);
    844       SkipAllFields(it);
    845       while (it.HasNextDirectMethod()) {
    846         WalkCodeItem(dex_file, it.GetMethodCodeItem());
    847         it.Next();
    848       }
    849       while (it.HasNextVirtualMethod()) {
    850         WalkCodeItem(dex_file, it.GetMethodCodeItem());
    851         it.Next();
    852       }
    853       DCHECK(!it.HasNext());
    854     }
    855 
    856     void WalkCodeItem(const DexFile& dex_file, const DexFile::CodeItem* code_item) {
    857       if (code_item == nullptr) {
    858         return;
    859       }
    860       const size_t code_item_size = code_item->insns_size_in_code_units_;
    861       const uint16_t* code_ptr = code_item->insns_;
    862       const uint16_t* code_end = code_item->insns_ + code_item_size;
    863 
    864       // If we inserted a new dex code item pointer, add to total code bytes.
    865       if (dex_code_item_ptrs_.insert(code_ptr).second) {
    866         dex_code_bytes_ += code_item_size * sizeof(code_ptr[0]);
    867       }
    868 
    869       while (code_ptr < code_end) {
    870         const Instruction* inst = Instruction::At(code_ptr);
    871         switch (inst->Opcode()) {
    872           case Instruction::CONST_STRING: {
    873             const dex::StringIndex string_index(inst->VRegB_21c());
    874             unique_string_ids_from_code_.insert(StringReference(&dex_file, string_index));
    875             ++num_string_ids_from_code_;
    876             break;
    877           }
    878           case Instruction::CONST_STRING_JUMBO: {
    879             const dex::StringIndex string_index(inst->VRegB_31c());
    880             unique_string_ids_from_code_.insert(StringReference(&dex_file, string_index));
    881             ++num_string_ids_from_code_;
    882             break;
    883           }
    884           default:
    885             break;
    886         }
    887 
    888         code_ptr += inst->SizeInCodeUnits();
    889       }
    890     }
    891 
    892     // Unique string ids loaded from dex code.
    893     std::set<StringReference, StringReferenceComparator> unique_string_ids_from_code_;
    894 
    895     // Total string ids loaded from dex code.
    896     size_t num_string_ids_from_code_ = 0;
    897 
    898     // Unique code pointers.
    899     std::set<const void*> dex_code_item_ptrs_;
    900 
    901     // Total "unique" dex code bytes.
    902     size_t dex_code_bytes_ = 0;
    903 
    904     // Other dex ids.
    905     size_t num_string_ids_ = 0;
    906     size_t num_method_ids_ = 0;
    907     size_t num_field_ids_ = 0;
    908     size_t num_type_ids_ = 0;
    909     size_t num_class_defs_ = 0;
    910   };
    911 
    912   bool DumpOatDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) {
    913     bool success = true;
    914     bool stop_analysis = false;
    915     os << "OatDexFile:\n";
    916     os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str());
    917     os << StringPrintf("checksum: 0x%08x\n", oat_dex_file.GetDexFileLocationChecksum());
    918 
    919     const uint8_t* const oat_file_begin = oat_dex_file.GetOatFile()->Begin();
    920     const uint8_t* const vdex_file_begin = oat_dex_file.GetOatFile()->DexBegin();
    921 
    922     // Print data range of the dex file embedded inside the corresponding vdex file.
    923     const uint8_t* const dex_file_pointer = oat_dex_file.GetDexFilePointer();
    924     uint32_t dex_offset = dchecked_integral_cast<uint32_t>(dex_file_pointer - vdex_file_begin);
    925     os << StringPrintf("dex-file: 0x%08x..0x%08x\n",
    926                        dex_offset,
    927                        dchecked_integral_cast<uint32_t>(dex_offset + oat_dex_file.FileSize() - 1));
    928 
    929     // Create the dex file early. A lot of print-out things depend on it.
    930     std::string error_msg;
    931     const DexFile* const dex_file = OpenDexFile(&oat_dex_file, &error_msg);
    932     if (dex_file == nullptr) {
    933       os << "NOT FOUND: " << error_msg << "\n\n";
    934       os << std::flush;
    935       return false;
    936     }
    937 
    938     // Print lookup table, if it exists.
    939     if (oat_dex_file.GetLookupTableData() != nullptr) {
    940       uint32_t table_offset = dchecked_integral_cast<uint32_t>(
    941           oat_dex_file.GetLookupTableData() - oat_file_begin);
    942       uint32_t table_size = TypeLookupTable::RawDataLength(dex_file->NumClassDefs());
    943       os << StringPrintf("type-table: 0x%08x..0x%08x\n",
    944                          table_offset,
    945                          table_offset + table_size - 1);
    946     }
    947 
    948     VariableIndentationOutputStream vios(&os);
    949     ScopedIndentation indent1(&vios);
    950     for (size_t class_def_index = 0;
    951          class_def_index < dex_file->NumClassDefs();
    952          class_def_index++) {
    953       const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
    954       const char* descriptor = dex_file->GetClassDescriptor(class_def);
    955 
    956       // TODO: Support regex
    957       if (DescriptorToDot(descriptor).find(options_.class_filter_) == std::string::npos) {
    958         continue;
    959       }
    960 
    961       uint32_t oat_class_offset = oat_dex_file.GetOatClassOffset(class_def_index);
    962       const OatFile::OatClass oat_class = oat_dex_file.GetOatClass(class_def_index);
    963       os << StringPrintf("%zd: %s (offset=0x%08x) (type_idx=%d)",
    964                          class_def_index, descriptor, oat_class_offset, class_def.class_idx_.index_)
    965          << " (" << oat_class.GetStatus() << ")"
    966          << " (" << oat_class.GetType() << ")\n";
    967       // TODO: include bitmap here if type is kOatClassSomeCompiled?
    968       if (options_.list_classes_) {
    969         continue;
    970       }
    971       if (!DumpOatClass(&vios, oat_class, *dex_file, class_def, &stop_analysis)) {
    972         success = false;
    973       }
    974       if (stop_analysis) {
    975         os << std::flush;
    976         return success;
    977       }
    978     }
    979     os << "\n";
    980     os << std::flush;
    981     return success;
    982   }
    983 
    984   bool ExportDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) {
    985     std::string error_msg;
    986     std::string dex_file_location = oat_dex_file.GetDexFileLocation();
    987 
    988     const DexFile* const dex_file = OpenDexFile(&oat_dex_file, &error_msg);
    989     if (dex_file == nullptr) {
    990       os << "Failed to open dex file '" << dex_file_location << "': " << error_msg;
    991       return false;
    992     }
    993     size_t fsize = oat_dex_file.FileSize();
    994 
    995     // Some quick checks just in case
    996     if (fsize == 0 || fsize < sizeof(DexFile::Header)) {
    997       os << "Invalid dex file\n";
    998       return false;
    999     }
   1000 
   1001     // Verify output directory exists
   1002     if (!OS::DirectoryExists(options_.export_dex_location_)) {
   1003       // TODO: Extend OS::DirectoryExists if symlink support is required
   1004       os << options_.export_dex_location_ << " output directory not found or symlink\n";
   1005       return false;
   1006     }
   1007 
   1008     // Beautify path names
   1009     if (dex_file_location.size() > PATH_MAX || dex_file_location.size() <= 0) {
   1010       return false;
   1011     }
   1012 
   1013     std::string dex_orig_name;
   1014     size_t dex_orig_pos = dex_file_location.rfind('/');
   1015     if (dex_orig_pos == std::string::npos)
   1016       dex_orig_name = dex_file_location;
   1017     else
   1018       dex_orig_name = dex_file_location.substr(dex_orig_pos + 1);
   1019 
   1020     // A more elegant approach to efficiently name user installed apps is welcome
   1021     if (dex_orig_name.size() == 8 &&
   1022         dex_orig_name.compare("base.apk") == 0 &&
   1023         dex_orig_pos != std::string::npos) {
   1024       dex_file_location.erase(dex_orig_pos, strlen("base.apk") + 1);
   1025       size_t apk_orig_pos = dex_file_location.rfind('/');
   1026       if (apk_orig_pos != std::string::npos) {
   1027         dex_orig_name = dex_file_location.substr(++apk_orig_pos);
   1028       }
   1029     }
   1030 
   1031     std::string out_dex_path(options_.export_dex_location_);
   1032     if (out_dex_path.back() != '/') {
   1033       out_dex_path.append("/");
   1034     }
   1035     out_dex_path.append(dex_orig_name);
   1036     out_dex_path.append("_export.dex");
   1037     if (out_dex_path.length() > PATH_MAX) {
   1038       return false;
   1039     }
   1040 
   1041     std::unique_ptr<File> file(OS::CreateEmptyFile(out_dex_path.c_str()));
   1042     if (file.get() == nullptr) {
   1043       os << "Failed to open output dex file " << out_dex_path;
   1044       return false;
   1045     }
   1046 
   1047     if (!file->WriteFully(dex_file->Begin(), fsize)) {
   1048       os << "Failed to write dex file";
   1049       file->Erase();
   1050       return false;
   1051     }
   1052 
   1053     if (file->FlushCloseOrErase() != 0) {
   1054       os << "Flush and close failed";
   1055       return false;
   1056     }
   1057 
   1058     os << StringPrintf("Dex file exported at %s (%zd bytes)\n", out_dex_path.c_str(), fsize);
   1059     os << std::flush;
   1060 
   1061     return true;
   1062   }
   1063 
   1064   static void SkipAllFields(ClassDataItemIterator& it) {
   1065     while (it.HasNextStaticField()) {
   1066       it.Next();
   1067     }
   1068     while (it.HasNextInstanceField()) {
   1069       it.Next();
   1070     }
   1071   }
   1072 
   1073   bool DumpOatClass(VariableIndentationOutputStream* vios,
   1074                     const OatFile::OatClass& oat_class, const DexFile& dex_file,
   1075                     const DexFile::ClassDef& class_def, bool* stop_analysis) {
   1076     bool success = true;
   1077     bool addr_found = false;
   1078     const uint8_t* class_data = dex_file.GetClassData(class_def);
   1079     if (class_data == nullptr) {  // empty class such as a marker interface?
   1080       vios->Stream() << std::flush;
   1081       return success;
   1082     }
   1083     ClassDataItemIterator it(dex_file, class_data);
   1084     SkipAllFields(it);
   1085     uint32_t class_method_index = 0;
   1086     while (it.HasNextDirectMethod()) {
   1087       if (!DumpOatMethod(vios, class_def, class_method_index, oat_class, dex_file,
   1088                          it.GetMemberIndex(), it.GetMethodCodeItem(),
   1089                          it.GetRawMemberAccessFlags(), &addr_found)) {
   1090         success = false;
   1091       }
   1092       if (addr_found) {
   1093         *stop_analysis = true;
   1094         return success;
   1095       }
   1096       class_method_index++;
   1097       it.Next();
   1098     }
   1099     while (it.HasNextVirtualMethod()) {
   1100       if (!DumpOatMethod(vios, class_def, class_method_index, oat_class, dex_file,
   1101                          it.GetMemberIndex(), it.GetMethodCodeItem(),
   1102                          it.GetRawMemberAccessFlags(), &addr_found)) {
   1103         success = false;
   1104       }
   1105       if (addr_found) {
   1106         *stop_analysis = true;
   1107         return success;
   1108       }
   1109       class_method_index++;
   1110       it.Next();
   1111     }
   1112     DCHECK(!it.HasNext());
   1113     vios->Stream() << std::flush;
   1114     return success;
   1115   }
   1116 
   1117   static constexpr uint32_t kPrologueBytes = 16;
   1118 
   1119   // When this was picked, the largest arm method was 55,256 bytes and arm64 was 50,412 bytes.
   1120   static constexpr uint32_t kMaxCodeSize = 100 * 1000;
   1121 
   1122   bool DumpOatMethod(VariableIndentationOutputStream* vios,
   1123                      const DexFile::ClassDef& class_def,
   1124                      uint32_t class_method_index,
   1125                      const OatFile::OatClass& oat_class, const DexFile& dex_file,
   1126                      uint32_t dex_method_idx, const DexFile::CodeItem* code_item,
   1127                      uint32_t method_access_flags, bool* addr_found) {
   1128     bool success = true;
   1129 
   1130     // TODO: Support regex
   1131     std::string method_name = dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
   1132     if (method_name.find(options_.method_filter_) == std::string::npos) {
   1133       return success;
   1134     }
   1135 
   1136     std::string pretty_method = dex_file.PrettyMethod(dex_method_idx, true);
   1137     vios->Stream() << StringPrintf("%d: %s (dex_method_idx=%d)\n",
   1138                                    class_method_index, pretty_method.c_str(),
   1139                                    dex_method_idx);
   1140     if (options_.list_methods_) return success;
   1141 
   1142     uint32_t oat_method_offsets_offset = oat_class.GetOatMethodOffsetsOffset(class_method_index);
   1143     const OatMethodOffsets* oat_method_offsets = oat_class.GetOatMethodOffsets(class_method_index);
   1144     const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_index);
   1145     uint32_t code_offset = oat_method.GetCodeOffset();
   1146     uint32_t code_size = oat_method.GetQuickCodeSize();
   1147     if (resolved_addr2instr_ != 0) {
   1148       if (resolved_addr2instr_ > code_offset + code_size) {
   1149         return success;
   1150       } else {
   1151         *addr_found = true;  // stop analyzing file at next iteration
   1152       }
   1153     }
   1154 
   1155     // Everything below is indented at least once.
   1156     ScopedIndentation indent1(vios);
   1157 
   1158     {
   1159       vios->Stream() << "DEX CODE:\n";
   1160       ScopedIndentation indent2(vios);
   1161       DumpDexCode(vios->Stream(), dex_file, code_item);
   1162     }
   1163 
   1164     std::unique_ptr<StackHandleScope<1>> hs;
   1165     std::unique_ptr<verifier::MethodVerifier> verifier;
   1166     if (Runtime::Current() != nullptr) {
   1167       // We need to have the handle scope stay live until after the verifier since the verifier has
   1168       // a handle to the dex cache from hs.
   1169       hs.reset(new StackHandleScope<1>(Thread::Current()));
   1170       vios->Stream() << "VERIFIER TYPE ANALYSIS:\n";
   1171       ScopedIndentation indent2(vios);
   1172       verifier.reset(DumpVerifier(vios, hs.get(),
   1173                                   dex_method_idx, &dex_file, class_def, code_item,
   1174                                   method_access_flags));
   1175     }
   1176     {
   1177       vios->Stream() << "OatMethodOffsets ";
   1178       if (options_.absolute_addresses_) {
   1179         vios->Stream() << StringPrintf("%p ", oat_method_offsets);
   1180       }
   1181       vios->Stream() << StringPrintf("(offset=0x%08x)\n", oat_method_offsets_offset);
   1182       if (oat_method_offsets_offset > oat_file_.Size()) {
   1183         vios->Stream() << StringPrintf(
   1184             "WARNING: oat method offsets offset 0x%08x is past end of file 0x%08zx.\n",
   1185             oat_method_offsets_offset, oat_file_.Size());
   1186         // If we can't read OatMethodOffsets, the rest of the data is dangerous to read.
   1187         vios->Stream() << std::flush;
   1188         return false;
   1189       }
   1190 
   1191       ScopedIndentation indent2(vios);
   1192       vios->Stream() << StringPrintf("code_offset: 0x%08x ", code_offset);
   1193       uint32_t aligned_code_begin = AlignCodeOffset(oat_method.GetCodeOffset());
   1194       if (aligned_code_begin > oat_file_.Size()) {
   1195         vios->Stream() << StringPrintf("WARNING: "
   1196                                        "code offset 0x%08x is past end of file 0x%08zx.\n",
   1197                                        aligned_code_begin, oat_file_.Size());
   1198         success = false;
   1199       }
   1200       vios->Stream() << "\n";
   1201     }
   1202     {
   1203       vios->Stream() << "OatQuickMethodHeader ";
   1204       uint32_t method_header_offset = oat_method.GetOatQuickMethodHeaderOffset();
   1205       const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
   1206       stats_.AddBitsIfUnique(Stats::kByteKindQuickMethodHeader,
   1207                              sizeof(*method_header) * kBitsPerByte,
   1208                              method_header);
   1209       if (options_.absolute_addresses_) {
   1210         vios->Stream() << StringPrintf("%p ", method_header);
   1211       }
   1212       vios->Stream() << StringPrintf("(offset=0x%08x)\n", method_header_offset);
   1213       if (method_header_offset > oat_file_.Size()) {
   1214         vios->Stream() << StringPrintf(
   1215             "WARNING: oat quick method header offset 0x%08x is past end of file 0x%08zx.\n",
   1216             method_header_offset, oat_file_.Size());
   1217         // If we can't read the OatQuickMethodHeader, the rest of the data is dangerous to read.
   1218         vios->Stream() << std::flush;
   1219         return false;
   1220       }
   1221 
   1222       ScopedIndentation indent2(vios);
   1223       vios->Stream() << "vmap_table: ";
   1224       if (options_.absolute_addresses_) {
   1225         vios->Stream() << StringPrintf("%p ", oat_method.GetVmapTable());
   1226       }
   1227       uint32_t vmap_table_offset = method_header ==
   1228           nullptr ? 0 : method_header->GetVmapTableOffset();
   1229       vios->Stream() << StringPrintf("(offset=0x%08x)\n", vmap_table_offset);
   1230 
   1231       size_t vmap_table_offset_limit =
   1232           (kIsVdexEnabled && IsMethodGeneratedByDexToDexCompiler(oat_method, code_item))
   1233               ? oat_file_.GetVdexFile()->Size()
   1234               : method_header->GetCode() - oat_file_.Begin();
   1235       if (vmap_table_offset >= vmap_table_offset_limit) {
   1236         vios->Stream() << StringPrintf("WARNING: "
   1237                                        "vmap table offset 0x%08x is past end of file 0x%08zx. "
   1238                                        "vmap table offset was loaded from offset 0x%08x.\n",
   1239                                        vmap_table_offset,
   1240                                        vmap_table_offset_limit,
   1241                                        oat_method.GetVmapTableOffsetOffset());
   1242         success = false;
   1243       } else if (options_.dump_vmap_) {
   1244         DumpVmapData(vios, oat_method, code_item);
   1245       }
   1246     }
   1247     {
   1248       vios->Stream() << "QuickMethodFrameInfo\n";
   1249 
   1250       ScopedIndentation indent2(vios);
   1251       vios->Stream()
   1252           << StringPrintf("frame_size_in_bytes: %zd\n", oat_method.GetFrameSizeInBytes());
   1253       vios->Stream() << StringPrintf("core_spill_mask: 0x%08x ", oat_method.GetCoreSpillMask());
   1254       DumpSpillMask(vios->Stream(), oat_method.GetCoreSpillMask(), false);
   1255       vios->Stream() << "\n";
   1256       vios->Stream() << StringPrintf("fp_spill_mask: 0x%08x ", oat_method.GetFpSpillMask());
   1257       DumpSpillMask(vios->Stream(), oat_method.GetFpSpillMask(), true);
   1258       vios->Stream() << "\n";
   1259     }
   1260     {
   1261       // Based on spill masks from QuickMethodFrameInfo so placed
   1262       // after it is dumped, but useful for understanding quick
   1263       // code, so dumped here.
   1264       ScopedIndentation indent2(vios);
   1265       DumpVregLocations(vios->Stream(), oat_method, code_item);
   1266     }
   1267     {
   1268       vios->Stream() << "CODE: ";
   1269       uint32_t code_size_offset = oat_method.GetQuickCodeSizeOffset();
   1270       if (code_size_offset > oat_file_.Size()) {
   1271         ScopedIndentation indent2(vios);
   1272         vios->Stream() << StringPrintf("WARNING: "
   1273                                        "code size offset 0x%08x is past end of file 0x%08zx.",
   1274                                        code_size_offset, oat_file_.Size());
   1275         success = false;
   1276       } else {
   1277         const void* code = oat_method.GetQuickCode();
   1278         uint32_t aligned_code_begin = AlignCodeOffset(code_offset);
   1279         uint64_t aligned_code_end = aligned_code_begin + code_size;
   1280         stats_.AddBitsIfUnique(Stats::kByteKindCode, code_size * kBitsPerByte, code);
   1281 
   1282         if (options_.absolute_addresses_) {
   1283           vios->Stream() << StringPrintf("%p ", code);
   1284         }
   1285         vios->Stream() << StringPrintf("(code_offset=0x%08x size_offset=0x%08x size=%u)%s\n",
   1286                                        code_offset,
   1287                                        code_size_offset,
   1288                                        code_size,
   1289                                        code != nullptr ? "..." : "");
   1290 
   1291         ScopedIndentation indent2(vios);
   1292         if (aligned_code_begin > oat_file_.Size()) {
   1293           vios->Stream() << StringPrintf("WARNING: "
   1294                                          "start of code at 0x%08x is past end of file 0x%08zx.",
   1295                                          aligned_code_begin, oat_file_.Size());
   1296           success = false;
   1297         } else if (aligned_code_end > oat_file_.Size()) {
   1298           vios->Stream() << StringPrintf(
   1299               "WARNING: "
   1300               "end of code at 0x%08" PRIx64 " is past end of file 0x%08zx. "
   1301               "code size is 0x%08x loaded from offset 0x%08x.\n",
   1302               aligned_code_end, oat_file_.Size(),
   1303               code_size, code_size_offset);
   1304           success = false;
   1305           if (options_.disassemble_code_) {
   1306             if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
   1307               DumpCode(vios, oat_method, code_item, true, kPrologueBytes);
   1308             }
   1309           }
   1310         } else if (code_size > kMaxCodeSize) {
   1311           vios->Stream() << StringPrintf(
   1312               "WARNING: "
   1313               "code size %d is bigger than max expected threshold of %d. "
   1314               "code size is 0x%08x loaded from offset 0x%08x.\n",
   1315               code_size, kMaxCodeSize,
   1316               code_size, code_size_offset);
   1317           success = false;
   1318           if (options_.disassemble_code_) {
   1319             if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
   1320               DumpCode(vios, oat_method, code_item, true, kPrologueBytes);
   1321             }
   1322           }
   1323         } else if (options_.disassemble_code_) {
   1324           DumpCode(vios, oat_method, code_item, !success, 0);
   1325         }
   1326       }
   1327     }
   1328     vios->Stream() << std::flush;
   1329     return success;
   1330   }
   1331 
   1332   void DumpSpillMask(std::ostream& os, uint32_t spill_mask, bool is_float) {
   1333     if (spill_mask == 0) {
   1334       return;
   1335     }
   1336     os << "(";
   1337     for (size_t i = 0; i < 32; i++) {
   1338       if ((spill_mask & (1 << i)) != 0) {
   1339         if (is_float) {
   1340           os << "fr" << i;
   1341         } else {
   1342           os << "r" << i;
   1343         }
   1344         spill_mask ^= 1 << i;  // clear bit
   1345         if (spill_mask != 0) {
   1346           os << ", ";
   1347         } else {
   1348           break;
   1349         }
   1350       }
   1351     }
   1352     os << ")";
   1353   }
   1354 
   1355   // Display data stored at the the vmap offset of an oat method.
   1356   void DumpVmapData(VariableIndentationOutputStream* vios,
   1357                     const OatFile::OatMethod& oat_method,
   1358                     const DexFile::CodeItem* code_item) {
   1359     if (IsMethodGeneratedByOptimizingCompiler(oat_method, code_item)) {
   1360       // The optimizing compiler outputs its CodeInfo data in the vmap table.
   1361       const void* raw_code_info = oat_method.GetVmapTable();
   1362       if (raw_code_info != nullptr) {
   1363         CodeInfo code_info(raw_code_info);
   1364         DCHECK(code_item != nullptr);
   1365         ScopedIndentation indent1(vios);
   1366         MethodInfo method_info = oat_method.GetOatQuickMethodHeader()->GetOptimizedMethodInfo();
   1367         DumpCodeInfo(vios, code_info, oat_method, *code_item, method_info);
   1368       }
   1369     } else if (IsMethodGeneratedByDexToDexCompiler(oat_method, code_item)) {
   1370       // We don't encode the size in the table, so just emit that we have quickened
   1371       // information.
   1372       ScopedIndentation indent(vios);
   1373       vios->Stream() << "quickened data\n";
   1374     } else {
   1375       // Otherwise, there is nothing to display.
   1376     }
   1377   }
   1378 
   1379   // Display a CodeInfo object emitted by the optimizing compiler.
   1380   void DumpCodeInfo(VariableIndentationOutputStream* vios,
   1381                     const CodeInfo& code_info,
   1382                     const OatFile::OatMethod& oat_method,
   1383                     const DexFile::CodeItem& code_item,
   1384                     const MethodInfo& method_info) {
   1385     code_info.Dump(vios,
   1386                    oat_method.GetCodeOffset(),
   1387                    code_item.registers_size_,
   1388                    options_.dump_code_info_stack_maps_,
   1389                    instruction_set_,
   1390                    method_info);
   1391   }
   1392 
   1393   void DumpVregLocations(std::ostream& os, const OatFile::OatMethod& oat_method,
   1394                          const DexFile::CodeItem* code_item) {
   1395     if (code_item != nullptr) {
   1396       size_t num_locals_ins = code_item->registers_size_;
   1397       size_t num_ins = code_item->ins_size_;
   1398       size_t num_locals = num_locals_ins - num_ins;
   1399       size_t num_outs = code_item->outs_size_;
   1400 
   1401       os << "vr_stack_locations:";
   1402       for (size_t reg = 0; reg <= num_locals_ins; reg++) {
   1403         // For readability, delimit the different kinds of VRs.
   1404         if (reg == num_locals_ins) {
   1405           os << "\n\tmethod*:";
   1406         } else if (reg == num_locals && num_ins > 0) {
   1407           os << "\n\tins:";
   1408         } else if (reg == 0 && num_locals > 0) {
   1409           os << "\n\tlocals:";
   1410         }
   1411 
   1412         uint32_t offset = StackVisitor::GetVRegOffsetFromQuickCode(
   1413             code_item,
   1414             oat_method.GetCoreSpillMask(),
   1415             oat_method.GetFpSpillMask(),
   1416             oat_method.GetFrameSizeInBytes(),
   1417             reg,
   1418             GetInstructionSet());
   1419         os << " v" << reg << "[sp + #" << offset << "]";
   1420       }
   1421 
   1422       for (size_t out_reg = 0; out_reg < num_outs; out_reg++) {
   1423         if (out_reg == 0) {
   1424           os << "\n\touts:";
   1425         }
   1426 
   1427         uint32_t offset = StackVisitor::GetOutVROffset(out_reg, GetInstructionSet());
   1428         os << " v" << out_reg << "[sp + #" << offset << "]";
   1429       }
   1430 
   1431       os << "\n";
   1432     }
   1433   }
   1434 
   1435   void DumpDexCode(std::ostream& os, const DexFile& dex_file, const DexFile::CodeItem* code_item) {
   1436     if (code_item != nullptr) {
   1437       size_t i = 0;
   1438       while (i < code_item->insns_size_in_code_units_) {
   1439         const Instruction* instruction = Instruction::At(&code_item->insns_[i]);
   1440         os << StringPrintf("0x%04zx: ", i) << instruction->DumpHexLE(5)
   1441            << StringPrintf("\t| %s\n", instruction->DumpString(&dex_file).c_str());
   1442         i += instruction->SizeInCodeUnits();
   1443       }
   1444     }
   1445   }
   1446 
   1447   // Has `oat_method` -- corresponding to the Dex `code_item` -- been compiled by
   1448   // the optimizing compiler?
   1449   static bool IsMethodGeneratedByOptimizingCompiler(const OatFile::OatMethod& oat_method,
   1450                                                     const DexFile::CodeItem* code_item) {
   1451     // If the native GC map is null and the Dex `code_item` is not
   1452     // null, then this method has been compiled with the optimizing
   1453     // compiler.
   1454     return oat_method.GetQuickCode() != nullptr &&
   1455            oat_method.GetVmapTable() != nullptr &&
   1456            code_item != nullptr;
   1457   }
   1458 
   1459   // Has `oat_method` -- corresponding to the Dex `code_item` -- been compiled by
   1460   // the dextodex compiler?
   1461   static bool IsMethodGeneratedByDexToDexCompiler(const OatFile::OatMethod& oat_method,
   1462                                                   const DexFile::CodeItem* code_item) {
   1463     // If the quick code is null, the Dex `code_item` is not
   1464     // null, and the vmap table is not null, then this method has been compiled
   1465     // with the dextodex compiler.
   1466     return oat_method.GetQuickCode() == nullptr &&
   1467            oat_method.GetVmapTable() != nullptr &&
   1468            code_item != nullptr;
   1469   }
   1470 
   1471   verifier::MethodVerifier* DumpVerifier(VariableIndentationOutputStream* vios,
   1472                                          StackHandleScope<1>* hs,
   1473                                          uint32_t dex_method_idx,
   1474                                          const DexFile* dex_file,
   1475                                          const DexFile::ClassDef& class_def,
   1476                                          const DexFile::CodeItem* code_item,
   1477                                          uint32_t method_access_flags) {
   1478     if ((method_access_flags & kAccNative) == 0) {
   1479       ScopedObjectAccess soa(Thread::Current());
   1480       Runtime* const runtime = Runtime::Current();
   1481       Handle<mirror::DexCache> dex_cache(
   1482           hs->NewHandle(runtime->GetClassLinker()->RegisterDexFile(*dex_file, nullptr)));
   1483       CHECK(dex_cache != nullptr);
   1484       DCHECK(options_.class_loader_ != nullptr);
   1485       return verifier::MethodVerifier::VerifyMethodAndDump(
   1486           soa.Self(), vios, dex_method_idx, dex_file, dex_cache, *options_.class_loader_,
   1487           class_def, code_item, nullptr, method_access_flags);
   1488     }
   1489 
   1490     return nullptr;
   1491   }
   1492 
   1493   // The StackMapsHelper provides the stack maps in the native PC order.
   1494   // For identical native PCs, the order from the CodeInfo is preserved.
   1495   class StackMapsHelper {
   1496    public:
   1497     explicit StackMapsHelper(const uint8_t* raw_code_info, InstructionSet instruction_set)
   1498         : code_info_(raw_code_info),
   1499           encoding_(code_info_.ExtractEncoding()),
   1500           number_of_stack_maps_(code_info_.GetNumberOfStackMaps(encoding_)),
   1501           indexes_(),
   1502           offset_(static_cast<uint32_t>(-1)),
   1503           stack_map_index_(0u),
   1504           instruction_set_(instruction_set) {
   1505       if (number_of_stack_maps_ != 0u) {
   1506         // Check if native PCs are ordered.
   1507         bool ordered = true;
   1508         StackMap last = code_info_.GetStackMapAt(0u, encoding_);
   1509         for (size_t i = 1; i != number_of_stack_maps_; ++i) {
   1510           StackMap current = code_info_.GetStackMapAt(i, encoding_);
   1511           if (last.GetNativePcOffset(encoding_.stack_map.encoding, instruction_set) >
   1512               current.GetNativePcOffset(encoding_.stack_map.encoding, instruction_set)) {
   1513             ordered = false;
   1514             break;
   1515           }
   1516           last = current;
   1517         }
   1518         if (!ordered) {
   1519           // Create indirection indexes for access in native PC order. We do not optimize
   1520           // for the fact that there can currently be only two separately ordered ranges,
   1521           // namely normal stack maps and catch-point stack maps.
   1522           indexes_.resize(number_of_stack_maps_);
   1523           std::iota(indexes_.begin(), indexes_.end(), 0u);
   1524           std::sort(indexes_.begin(),
   1525                     indexes_.end(),
   1526                     [this](size_t lhs, size_t rhs) {
   1527                       StackMap left = code_info_.GetStackMapAt(lhs, encoding_);
   1528                       uint32_t left_pc = left.GetNativePcOffset(encoding_.stack_map.encoding,
   1529                                                                 instruction_set_);
   1530                       StackMap right = code_info_.GetStackMapAt(rhs, encoding_);
   1531                       uint32_t right_pc = right.GetNativePcOffset(encoding_.stack_map.encoding,
   1532                                                                   instruction_set_);
   1533                       // If the PCs are the same, compare indexes to preserve the original order.
   1534                       return (left_pc < right_pc) || (left_pc == right_pc && lhs < rhs);
   1535                     });
   1536         }
   1537         offset_ = GetStackMapAt(0).GetNativePcOffset(encoding_.stack_map.encoding,
   1538                                                      instruction_set_);
   1539       }
   1540     }
   1541 
   1542     const CodeInfo& GetCodeInfo() const {
   1543       return code_info_;
   1544     }
   1545 
   1546     const CodeInfoEncoding& GetEncoding() const {
   1547       return encoding_;
   1548     }
   1549 
   1550     uint32_t GetOffset() const {
   1551       return offset_;
   1552     }
   1553 
   1554     StackMap GetStackMap() const {
   1555       return GetStackMapAt(stack_map_index_);
   1556     }
   1557 
   1558     void Next() {
   1559       ++stack_map_index_;
   1560       offset_ = (stack_map_index_ == number_of_stack_maps_)
   1561           ? static_cast<uint32_t>(-1)
   1562           : GetStackMapAt(stack_map_index_).GetNativePcOffset(encoding_.stack_map.encoding,
   1563                                                               instruction_set_);
   1564     }
   1565 
   1566    private:
   1567     StackMap GetStackMapAt(size_t i) const {
   1568       if (!indexes_.empty()) {
   1569         i = indexes_[i];
   1570       }
   1571       DCHECK_LT(i, number_of_stack_maps_);
   1572       return code_info_.GetStackMapAt(i, encoding_);
   1573     }
   1574 
   1575     const CodeInfo code_info_;
   1576     const CodeInfoEncoding encoding_;
   1577     const size_t number_of_stack_maps_;
   1578     dchecked_vector<size_t> indexes_;  // Used if stack map native PCs are not ordered.
   1579     uint32_t offset_;
   1580     size_t stack_map_index_;
   1581     const InstructionSet instruction_set_;
   1582   };
   1583 
   1584   void DumpCode(VariableIndentationOutputStream* vios,
   1585                 const OatFile::OatMethod& oat_method, const DexFile::CodeItem* code_item,
   1586                 bool bad_input, size_t code_size) {
   1587     const void* quick_code = oat_method.GetQuickCode();
   1588 
   1589     if (code_size == 0) {
   1590       code_size = oat_method.GetQuickCodeSize();
   1591     }
   1592     if (code_size == 0 || quick_code == nullptr) {
   1593       vios->Stream() << "NO CODE!\n";
   1594       return;
   1595     } else if (!bad_input && IsMethodGeneratedByOptimizingCompiler(oat_method, code_item)) {
   1596       // The optimizing compiler outputs its CodeInfo data in the vmap table.
   1597       StackMapsHelper helper(oat_method.GetVmapTable(), instruction_set_);
   1598       MethodInfo method_info(oat_method.GetOatQuickMethodHeader()->GetOptimizedMethodInfo());
   1599       {
   1600         CodeInfoEncoding encoding(helper.GetEncoding());
   1601         StackMapEncoding stack_map_encoding(encoding.stack_map.encoding);
   1602         const size_t num_stack_maps = encoding.stack_map.num_entries;
   1603         if (stats_.AddBitsIfUnique(Stats::kByteKindCodeInfoEncoding,
   1604                                    encoding.HeaderSize() * kBitsPerByte,
   1605                                    oat_method.GetVmapTable())) {
   1606           // Stack maps
   1607           stats_.AddBits(
   1608               Stats::kByteKindStackMapNativePc,
   1609               stack_map_encoding.GetNativePcEncoding().BitSize() * num_stack_maps);
   1610           stats_.AddBits(
   1611               Stats::kByteKindStackMapDexPc,
   1612               stack_map_encoding.GetDexPcEncoding().BitSize() * num_stack_maps);
   1613           stats_.AddBits(
   1614               Stats::kByteKindStackMapDexRegisterMap,
   1615               stack_map_encoding.GetDexRegisterMapEncoding().BitSize() * num_stack_maps);
   1616           stats_.AddBits(
   1617               Stats::kByteKindStackMapInlineInfoIndex,
   1618               stack_map_encoding.GetInlineInfoEncoding().BitSize() * num_stack_maps);
   1619           stats_.AddBits(
   1620               Stats::kByteKindStackMapRegisterMaskIndex,
   1621               stack_map_encoding.GetRegisterMaskIndexEncoding().BitSize() * num_stack_maps);
   1622           stats_.AddBits(
   1623               Stats::kByteKindStackMapStackMaskIndex,
   1624               stack_map_encoding.GetStackMaskIndexEncoding().BitSize() * num_stack_maps);
   1625 
   1626           // Stack masks
   1627           stats_.AddBits(
   1628               Stats::kByteKindCodeInfoStackMasks,
   1629               encoding.stack_mask.encoding.BitSize() * encoding.stack_mask.num_entries);
   1630 
   1631           // Register masks
   1632           stats_.AddBits(
   1633               Stats::kByteKindCodeInfoRegisterMasks,
   1634               encoding.register_mask.encoding.BitSize() * encoding.register_mask.num_entries);
   1635 
   1636           // Invoke infos
   1637           if (encoding.invoke_info.num_entries > 0u) {
   1638             stats_.AddBits(
   1639                 Stats::kByteKindCodeInfoInvokeInfo,
   1640                 encoding.invoke_info.encoding.BitSize() * encoding.invoke_info.num_entries);
   1641           }
   1642 
   1643           // Location catalog
   1644           const size_t location_catalog_bytes =
   1645               helper.GetCodeInfo().GetDexRegisterLocationCatalogSize(encoding);
   1646           stats_.AddBits(Stats::kByteKindCodeInfoLocationCatalog,
   1647                          kBitsPerByte * location_catalog_bytes);
   1648           // Dex register bytes.
   1649           const size_t dex_register_bytes =
   1650               helper.GetCodeInfo().GetDexRegisterMapsSize(encoding, code_item->registers_size_);
   1651           stats_.AddBits(
   1652               Stats::kByteKindCodeInfoDexRegisterMap,
   1653               kBitsPerByte * dex_register_bytes);
   1654 
   1655           // Inline infos.
   1656           const size_t num_inline_infos = encoding.inline_info.num_entries;
   1657           if (num_inline_infos > 0u) {
   1658             stats_.AddBits(
   1659                 Stats::kByteKindInlineInfoMethodIndexIdx,
   1660                 encoding.inline_info.encoding.GetMethodIndexIdxEncoding().BitSize() *
   1661                     num_inline_infos);
   1662             stats_.AddBits(
   1663                 Stats::kByteKindInlineInfoDexPc,
   1664                 encoding.inline_info.encoding.GetDexPcEncoding().BitSize() * num_inline_infos);
   1665             stats_.AddBits(
   1666                 Stats::kByteKindInlineInfoExtraData,
   1667                 encoding.inline_info.encoding.GetExtraDataEncoding().BitSize() * num_inline_infos);
   1668             stats_.AddBits(
   1669                 Stats::kByteKindInlineInfoDexRegisterMap,
   1670                 encoding.inline_info.encoding.GetDexRegisterMapEncoding().BitSize() *
   1671                     num_inline_infos);
   1672             stats_.AddBits(Stats::kByteKindInlineInfoIsLast, num_inline_infos);
   1673           }
   1674         }
   1675       }
   1676       const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
   1677       size_t offset = 0;
   1678       while (offset < code_size) {
   1679         offset += disassembler_->Dump(vios->Stream(), quick_native_pc + offset);
   1680         if (offset == helper.GetOffset()) {
   1681           ScopedIndentation indent1(vios);
   1682           StackMap stack_map = helper.GetStackMap();
   1683           DCHECK(stack_map.IsValid());
   1684           stack_map.Dump(vios,
   1685                          helper.GetCodeInfo(),
   1686                          helper.GetEncoding(),
   1687                          method_info,
   1688                          oat_method.GetCodeOffset(),
   1689                          code_item->registers_size_,
   1690                          instruction_set_);
   1691           do {
   1692             helper.Next();
   1693             // There may be multiple stack maps at a given PC. We display only the first one.
   1694           } while (offset == helper.GetOffset());
   1695         }
   1696         DCHECK_LT(offset, helper.GetOffset());
   1697       }
   1698     } else {
   1699       const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
   1700       size_t offset = 0;
   1701       while (offset < code_size) {
   1702         offset += disassembler_->Dump(vios->Stream(), quick_native_pc + offset);
   1703       }
   1704     }
   1705   }
   1706 
   1707   const OatFile& oat_file_;
   1708   const std::vector<const OatFile::OatDexFile*> oat_dex_files_;
   1709   const OatDumperOptions& options_;
   1710   uint32_t resolved_addr2instr_;
   1711   const InstructionSet instruction_set_;
   1712   std::set<uintptr_t> offsets_;
   1713   Disassembler* disassembler_;
   1714   Stats stats_;
   1715 };
   1716 
   1717 class ImageDumper {
   1718  public:
   1719   ImageDumper(std::ostream* os,
   1720               gc::space::ImageSpace& image_space,
   1721               const ImageHeader& image_header,
   1722               OatDumperOptions* oat_dumper_options)
   1723       : os_(os),
   1724         vios_(os),
   1725         indent1_(&vios_),
   1726         image_space_(image_space),
   1727         image_header_(image_header),
   1728         oat_dumper_options_(oat_dumper_options) {}
   1729 
   1730   bool Dump() REQUIRES_SHARED(Locks::mutator_lock_) {
   1731     std::ostream& os = *os_;
   1732     std::ostream& indent_os = vios_.Stream();
   1733 
   1734     os << "MAGIC: " << image_header_.GetMagic() << "\n\n";
   1735 
   1736     os << "IMAGE LOCATION: " << image_space_.GetImageLocation() << "\n\n";
   1737 
   1738     os << "IMAGE BEGIN: " << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n";
   1739 
   1740     os << "IMAGE SIZE: " << image_header_.GetImageSize() << "\n\n";
   1741 
   1742     for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
   1743       auto section = static_cast<ImageHeader::ImageSections>(i);
   1744       os << "IMAGE SECTION " << section << ": " << image_header_.GetImageSection(section) << "\n\n";
   1745     }
   1746 
   1747     os << "OAT CHECKSUM: " << StringPrintf("0x%08x\n\n", image_header_.GetOatChecksum());
   1748 
   1749     os << "OAT FILE BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatFileBegin()) << "\n\n";
   1750 
   1751     os << "OAT DATA BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatDataBegin()) << "\n\n";
   1752 
   1753     os << "OAT DATA END:" << reinterpret_cast<void*>(image_header_.GetOatDataEnd()) << "\n\n";
   1754 
   1755     os << "OAT FILE END:" << reinterpret_cast<void*>(image_header_.GetOatFileEnd()) << "\n\n";
   1756 
   1757     os << "PATCH DELTA:" << image_header_.GetPatchDelta() << "\n\n";
   1758 
   1759     os << "COMPILE PIC: " << (image_header_.CompilePic() ? "yes" : "no") << "\n\n";
   1760 
   1761     {
   1762       os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n";
   1763       static_assert(arraysize(image_roots_descriptions_) ==
   1764           static_cast<size_t>(ImageHeader::kImageRootsMax), "sizes must match");
   1765       DCHECK_LE(image_header_.GetImageRoots()->GetLength(), ImageHeader::kImageRootsMax);
   1766       for (int32_t i = 0, size = image_header_.GetImageRoots()->GetLength(); i != size; ++i) {
   1767         ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
   1768         const char* image_root_description = image_roots_descriptions_[i];
   1769         mirror::Object* image_root_object = image_header_.GetImageRoot(image_root);
   1770         indent_os << StringPrintf("%s: %p\n", image_root_description, image_root_object);
   1771         if (image_root_object != nullptr && image_root_object->IsObjectArray()) {
   1772           mirror::ObjectArray<mirror::Object>* image_root_object_array
   1773               = image_root_object->AsObjectArray<mirror::Object>();
   1774           ScopedIndentation indent2(&vios_);
   1775           for (int j = 0; j < image_root_object_array->GetLength(); j++) {
   1776             mirror::Object* value = image_root_object_array->Get(j);
   1777             size_t run = 0;
   1778             for (int32_t k = j + 1; k < image_root_object_array->GetLength(); k++) {
   1779               if (value == image_root_object_array->Get(k)) {
   1780                 run++;
   1781               } else {
   1782                 break;
   1783               }
   1784             }
   1785             if (run == 0) {
   1786               indent_os << StringPrintf("%d: ", j);
   1787             } else {
   1788               indent_os << StringPrintf("%d to %zd: ", j, j + run);
   1789               j = j + run;
   1790             }
   1791             if (value != nullptr) {
   1792               PrettyObjectValue(indent_os, value->GetClass(), value);
   1793             } else {
   1794               indent_os << j << ": null\n";
   1795             }
   1796           }
   1797         }
   1798       }
   1799     }
   1800 
   1801     {
   1802       os << "METHOD ROOTS\n";
   1803       static_assert(arraysize(image_methods_descriptions_) ==
   1804           static_cast<size_t>(ImageHeader::kImageMethodsCount), "sizes must match");
   1805       for (int i = 0; i < ImageHeader::kImageMethodsCount; i++) {
   1806         auto image_root = static_cast<ImageHeader::ImageMethod>(i);
   1807         const char* description = image_methods_descriptions_[i];
   1808         auto* image_method = image_header_.GetImageMethod(image_root);
   1809         indent_os << StringPrintf("%s: %p\n", description, image_method);
   1810       }
   1811     }
   1812     os << "\n";
   1813 
   1814     Runtime* const runtime = Runtime::Current();
   1815     ClassLinker* class_linker = runtime->GetClassLinker();
   1816     std::string image_filename = image_space_.GetImageFilename();
   1817     std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(image_filename);
   1818     os << "OAT LOCATION: " << oat_location;
   1819     os << "\n";
   1820     std::string error_msg;
   1821     const OatFile* oat_file = image_space_.GetOatFile();
   1822     if (oat_file == nullptr) {
   1823       oat_file = runtime->GetOatFileManager().FindOpenedOatFileFromOatLocation(oat_location);
   1824     }
   1825     if (oat_file == nullptr) {
   1826       oat_file = OatFile::Open(oat_location,
   1827                                oat_location,
   1828                                nullptr,
   1829                                nullptr,
   1830                                false,
   1831                                /*low_4gb*/false,
   1832                                nullptr,
   1833                                &error_msg);
   1834     }
   1835     if (oat_file == nullptr) {
   1836       os << "OAT FILE NOT FOUND: " << error_msg << "\n";
   1837       return EXIT_FAILURE;
   1838     }
   1839     os << "\n";
   1840 
   1841     stats_.oat_file_bytes = oat_file->Size();
   1842 
   1843     oat_dumper_.reset(new OatDumper(*oat_file, *oat_dumper_options_));
   1844 
   1845     for (const OatFile::OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) {
   1846       CHECK(oat_dex_file != nullptr);
   1847       stats_.oat_dex_file_sizes.push_back(std::make_pair(oat_dex_file->GetDexFileLocation(),
   1848                                                          oat_dex_file->FileSize()));
   1849     }
   1850 
   1851     os << "OBJECTS:\n" << std::flush;
   1852 
   1853     // Loop through the image space and dump its objects.
   1854     gc::Heap* heap = runtime->GetHeap();
   1855     Thread* self = Thread::Current();
   1856     {
   1857       {
   1858         WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
   1859         heap->FlushAllocStack();
   1860       }
   1861       // Since FlushAllocStack() above resets the (active) allocation
   1862       // stack. Need to revoke the thread-local allocation stacks that
   1863       // point into it.
   1864       ScopedThreadSuspension sts(self, kNative);
   1865       ScopedSuspendAll ssa(__FUNCTION__);
   1866       heap->RevokeAllThreadLocalAllocationStacks(self);
   1867     }
   1868     {
   1869       // Mark dex caches.
   1870       dex_caches_.clear();
   1871       {
   1872         ReaderMutexLock mu(self, *Locks::dex_lock_);
   1873         for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
   1874           ObjPtr<mirror::DexCache> dex_cache =
   1875               ObjPtr<mirror::DexCache>::DownCast(self->DecodeJObject(data.weak_root));
   1876           if (dex_cache != nullptr) {
   1877             dex_caches_.insert(dex_cache.Ptr());
   1878           }
   1879         }
   1880       }
   1881       ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
   1882       // Dump the normal objects before ArtMethods.
   1883       image_space_.GetLiveBitmap()->Walk(ImageDumper::Callback, this);
   1884       indent_os << "\n";
   1885       // TODO: Dump fields.
   1886       // Dump methods after.
   1887       DumpArtMethodVisitor visitor(this);
   1888       image_header_.VisitPackedArtMethods(&visitor,
   1889                                           image_space_.Begin(),
   1890                                           image_header_.GetPointerSize());
   1891       // Dump the large objects separately.
   1892       heap->GetLargeObjectsSpace()->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
   1893       indent_os << "\n";
   1894     }
   1895     os << "STATS:\n" << std::flush;
   1896     std::unique_ptr<File> file(OS::OpenFileForReading(image_filename.c_str()));
   1897     size_t data_size = image_header_.GetDataSize();  // stored size in file.
   1898     if (file == nullptr) {
   1899       LOG(WARNING) << "Failed to find image in " << image_filename;
   1900     } else {
   1901       stats_.file_bytes = file->GetLength();
   1902       // If the image is compressed, adjust to decompressed size.
   1903       size_t uncompressed_size = image_header_.GetImageSize() - sizeof(ImageHeader);
   1904       if (image_header_.GetStorageMode() == ImageHeader::kStorageModeUncompressed) {
   1905         DCHECK_EQ(uncompressed_size, data_size) << "Sizes should match for uncompressed image";
   1906       }
   1907       stats_.file_bytes += uncompressed_size - data_size;
   1908     }
   1909     size_t header_bytes = sizeof(ImageHeader);
   1910     const auto& object_section = image_header_.GetImageSection(ImageHeader::kSectionObjects);
   1911     const auto& field_section = image_header_.GetImageSection(ImageHeader::kSectionArtFields);
   1912     const auto& method_section = image_header_.GetMethodsSection();
   1913     const auto& dex_cache_arrays_section = image_header_.GetImageSection(
   1914         ImageHeader::kSectionDexCacheArrays);
   1915     const auto& intern_section = image_header_.GetImageSection(
   1916         ImageHeader::kSectionInternedStrings);
   1917     const auto& class_table_section = image_header_.GetImageSection(
   1918         ImageHeader::kSectionClassTable);
   1919     const auto& bitmap_section = image_header_.GetImageSection(ImageHeader::kSectionImageBitmap);
   1920 
   1921     stats_.header_bytes = header_bytes;
   1922 
   1923     // Objects are kObjectAlignment-aligned.
   1924     // CHECK_EQ(RoundUp(header_bytes, kObjectAlignment), object_section.Offset());
   1925     if (object_section.Offset() > header_bytes) {
   1926       stats_.alignment_bytes += object_section.Offset() - header_bytes;
   1927     }
   1928 
   1929     // Field section is 4-byte aligned.
   1930     constexpr size_t kFieldSectionAlignment = 4U;
   1931     uint32_t end_objects = object_section.Offset() + object_section.Size();
   1932     CHECK_EQ(RoundUp(end_objects, kFieldSectionAlignment), field_section.Offset());
   1933     stats_.alignment_bytes += field_section.Offset() - end_objects;
   1934 
   1935     // Method section is 4/8 byte aligned depending on target. Just check for 4-byte alignment.
   1936     uint32_t end_fields = field_section.Offset() + field_section.Size();
   1937     CHECK_ALIGNED(method_section.Offset(), 4);
   1938     stats_.alignment_bytes += method_section.Offset() - end_fields;
   1939 
   1940     // Dex cache arrays section is aligned depending on the target. Just check for 4-byte alignment.
   1941     uint32_t end_methods = method_section.Offset() + method_section.Size();
   1942     CHECK_ALIGNED(dex_cache_arrays_section.Offset(), 4);
   1943     stats_.alignment_bytes += dex_cache_arrays_section.Offset() - end_methods;
   1944 
   1945     // Intern table is 8-byte aligned.
   1946     uint32_t end_caches = dex_cache_arrays_section.Offset() + dex_cache_arrays_section.Size();
   1947     CHECK_EQ(RoundUp(end_caches, 8U), intern_section.Offset());
   1948     stats_.alignment_bytes += intern_section.Offset() - end_caches;
   1949 
   1950     // Add space between intern table and class table.
   1951     uint32_t end_intern = intern_section.Offset() + intern_section.Size();
   1952     stats_.alignment_bytes += class_table_section.Offset() - end_intern;
   1953 
   1954     // Add space between end of image data and bitmap. Expect the bitmap to be page-aligned.
   1955     const size_t bitmap_offset = sizeof(ImageHeader) + data_size;
   1956     CHECK_ALIGNED(bitmap_section.Offset(), kPageSize);
   1957     stats_.alignment_bytes += RoundUp(bitmap_offset, kPageSize) - bitmap_offset;
   1958 
   1959     stats_.bitmap_bytes += bitmap_section.Size();
   1960     stats_.art_field_bytes += field_section.Size();
   1961     stats_.art_method_bytes += method_section.Size();
   1962     stats_.dex_cache_arrays_bytes += dex_cache_arrays_section.Size();
   1963     stats_.interned_strings_bytes += intern_section.Size();
   1964     stats_.class_table_bytes += class_table_section.Size();
   1965     stats_.Dump(os, indent_os);
   1966     os << "\n";
   1967 
   1968     os << std::flush;
   1969 
   1970     return oat_dumper_->Dump(os);
   1971   }
   1972 
   1973  private:
   1974   class DumpArtMethodVisitor : public ArtMethodVisitor {
   1975    public:
   1976     explicit DumpArtMethodVisitor(ImageDumper* image_dumper) : image_dumper_(image_dumper) {}
   1977 
   1978     virtual void Visit(ArtMethod* method) OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) {
   1979       std::ostream& indent_os = image_dumper_->vios_.Stream();
   1980       indent_os << method << " " << " ArtMethod: " << ArtMethod::PrettyMethod(method) << "\n";
   1981       image_dumper_->DumpMethod(method, indent_os);
   1982       indent_os << "\n";
   1983     }
   1984 
   1985    private:
   1986     ImageDumper* const image_dumper_;
   1987   };
   1988 
   1989   static void PrettyObjectValue(std::ostream& os,
   1990                                 ObjPtr<mirror::Class> type,
   1991                                 ObjPtr<mirror::Object> value)
   1992       REQUIRES_SHARED(Locks::mutator_lock_) {
   1993     CHECK(type != nullptr);
   1994     if (value == nullptr) {
   1995       os << StringPrintf("null   %s\n", type->PrettyDescriptor().c_str());
   1996     } else if (type->IsStringClass()) {
   1997       mirror::String* string = value->AsString();
   1998       os << StringPrintf("%p   String: %s\n", string,
   1999                          PrintableString(string->ToModifiedUtf8().c_str()).c_str());
   2000     } else if (type->IsClassClass()) {
   2001       mirror::Class* klass = value->AsClass();
   2002       os << StringPrintf("%p   Class: %s\n", klass, mirror::Class::PrettyDescriptor(klass).c_str());
   2003     } else {
   2004       os << StringPrintf("%p   %s\n", value.Ptr(), type->PrettyDescriptor().c_str());
   2005     }
   2006   }
   2007 
   2008   static void PrintField(std::ostream& os, ArtField* field, ObjPtr<mirror::Object> obj)
   2009       REQUIRES_SHARED(Locks::mutator_lock_) {
   2010     os << StringPrintf("%s: ", field->GetName());
   2011     switch (field->GetTypeAsPrimitiveType()) {
   2012       case Primitive::kPrimLong:
   2013         os << StringPrintf("%" PRId64 " (0x%" PRIx64 ")\n", field->Get64(obj), field->Get64(obj));
   2014         break;
   2015       case Primitive::kPrimDouble:
   2016         os << StringPrintf("%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj));
   2017         break;
   2018       case Primitive::kPrimFloat:
   2019         os << StringPrintf("%f (%a)\n", field->GetFloat(obj), field->GetFloat(obj));
   2020         break;
   2021       case Primitive::kPrimInt:
   2022         os << StringPrintf("%d (0x%x)\n", field->Get32(obj), field->Get32(obj));
   2023         break;
   2024       case Primitive::kPrimChar:
   2025         os << StringPrintf("%u (0x%x)\n", field->GetChar(obj), field->GetChar(obj));
   2026         break;
   2027       case Primitive::kPrimShort:
   2028         os << StringPrintf("%d (0x%x)\n", field->GetShort(obj), field->GetShort(obj));
   2029         break;
   2030       case Primitive::kPrimBoolean:
   2031         os << StringPrintf("%s (0x%x)\n", field->GetBoolean(obj) ? "true" : "false",
   2032             field->GetBoolean(obj));
   2033         break;
   2034       case Primitive::kPrimByte:
   2035         os << StringPrintf("%d (0x%x)\n", field->GetByte(obj), field->GetByte(obj));
   2036         break;
   2037       case Primitive::kPrimNot: {
   2038         // Get the value, don't compute the type unless it is non-null as we don't want
   2039         // to cause class loading.
   2040         ObjPtr<mirror::Object> value = field->GetObj(obj);
   2041         if (value == nullptr) {
   2042           os << StringPrintf("null   %s\n", PrettyDescriptor(field->GetTypeDescriptor()).c_str());
   2043         } else {
   2044           // Grab the field type without causing resolution.
   2045           ObjPtr<mirror::Class> field_type = field->GetType<false>();
   2046           if (field_type != nullptr) {
   2047             PrettyObjectValue(os, field_type, value);
   2048           } else {
   2049             os << StringPrintf("%p   %s\n",
   2050                                value.Ptr(),
   2051                                PrettyDescriptor(field->GetTypeDescriptor()).c_str());
   2052           }
   2053         }
   2054         break;
   2055       }
   2056       default:
   2057         os << "unexpected field type: " << field->GetTypeDescriptor() << "\n";
   2058         break;
   2059     }
   2060   }
   2061 
   2062   static void DumpFields(std::ostream& os, mirror::Object* obj, mirror::Class* klass)
   2063       REQUIRES_SHARED(Locks::mutator_lock_) {
   2064     mirror::Class* super = klass->GetSuperClass();
   2065     if (super != nullptr) {
   2066       DumpFields(os, obj, super);
   2067     }
   2068     for (ArtField& field : klass->GetIFields()) {
   2069       PrintField(os, &field, obj);
   2070     }
   2071   }
   2072 
   2073   bool InDumpSpace(const mirror::Object* object) {
   2074     return image_space_.Contains(object);
   2075   }
   2076 
   2077   const void* GetQuickOatCodeBegin(ArtMethod* m) REQUIRES_SHARED(Locks::mutator_lock_) {
   2078     const void* quick_code = m->GetEntryPointFromQuickCompiledCodePtrSize(
   2079         image_header_.GetPointerSize());
   2080     if (Runtime::Current()->GetClassLinker()->IsQuickResolutionStub(quick_code)) {
   2081       quick_code = oat_dumper_->GetQuickOatCode(m);
   2082     }
   2083     if (oat_dumper_->GetInstructionSet() == kThumb2) {
   2084       quick_code = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(quick_code) & ~0x1);
   2085     }
   2086     return quick_code;
   2087   }
   2088 
   2089   uint32_t GetQuickOatCodeSize(ArtMethod* m)
   2090       REQUIRES_SHARED(Locks::mutator_lock_) {
   2091     const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetQuickOatCodeBegin(m));
   2092     if (oat_code_begin == nullptr) {
   2093       return 0;
   2094     }
   2095     return oat_code_begin[-1];
   2096   }
   2097 
   2098   const void* GetQuickOatCodeEnd(ArtMethod* m)
   2099       REQUIRES_SHARED(Locks::mutator_lock_) {
   2100     const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetQuickOatCodeBegin(m));
   2101     if (oat_code_begin == nullptr) {
   2102       return nullptr;
   2103     }
   2104     return oat_code_begin + GetQuickOatCodeSize(m);
   2105   }
   2106 
   2107   static void Callback(mirror::Object* obj, void* arg) REQUIRES_SHARED(Locks::mutator_lock_) {
   2108     DCHECK(obj != nullptr);
   2109     DCHECK(arg != nullptr);
   2110     ImageDumper* state = reinterpret_cast<ImageDumper*>(arg);
   2111     if (!state->InDumpSpace(obj)) {
   2112       return;
   2113     }
   2114 
   2115     size_t object_bytes = obj->SizeOf();
   2116     size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
   2117     state->stats_.object_bytes += object_bytes;
   2118     state->stats_.alignment_bytes += alignment_bytes;
   2119 
   2120     std::ostream& os = state->vios_.Stream();
   2121 
   2122     mirror::Class* obj_class = obj->GetClass();
   2123     if (obj_class->IsArrayClass()) {
   2124       os << StringPrintf("%p: %s length:%d\n", obj, obj_class->PrettyDescriptor().c_str(),
   2125                          obj->AsArray()->GetLength());
   2126     } else if (obj->IsClass()) {
   2127       mirror::Class* klass = obj->AsClass();
   2128       os << StringPrintf("%p: java.lang.Class \"%s\" (", obj,
   2129                          mirror::Class::PrettyDescriptor(klass).c_str())
   2130          << klass->GetStatus() << ")\n";
   2131     } else if (obj_class->IsStringClass()) {
   2132       os << StringPrintf("%p: java.lang.String %s\n", obj,
   2133                          PrintableString(obj->AsString()->ToModifiedUtf8().c_str()).c_str());
   2134     } else {
   2135       os << StringPrintf("%p: %s\n", obj, obj_class->PrettyDescriptor().c_str());
   2136     }
   2137     ScopedIndentation indent1(&state->vios_);
   2138     DumpFields(os, obj, obj_class);
   2139     const PointerSize image_pointer_size = state->image_header_.GetPointerSize();
   2140     if (obj->IsObjectArray()) {
   2141       auto* obj_array = obj->AsObjectArray<mirror::Object>();
   2142       for (int32_t i = 0, length = obj_array->GetLength(); i < length; i++) {
   2143         mirror::Object* value = obj_array->Get(i);
   2144         size_t run = 0;
   2145         for (int32_t j = i + 1; j < length; j++) {
   2146           if (value == obj_array->Get(j)) {
   2147             run++;
   2148           } else {
   2149             break;
   2150           }
   2151         }
   2152         if (run == 0) {
   2153           os << StringPrintf("%d: ", i);
   2154         } else {
   2155           os << StringPrintf("%d to %zd: ", i, i + run);
   2156           i = i + run;
   2157         }
   2158         mirror::Class* value_class =
   2159             (value == nullptr) ? obj_class->GetComponentType() : value->GetClass();
   2160         PrettyObjectValue(os, value_class, value);
   2161       }
   2162     } else if (obj->IsClass()) {
   2163       mirror::Class* klass = obj->AsClass();
   2164       if (klass->NumStaticFields() != 0) {
   2165         os << "STATICS:\n";
   2166         ScopedIndentation indent2(&state->vios_);
   2167         for (ArtField& field : klass->GetSFields()) {
   2168           PrintField(os, &field, field.GetDeclaringClass());
   2169         }
   2170       }
   2171     } else {
   2172       auto it = state->dex_caches_.find(obj);
   2173       if (it != state->dex_caches_.end()) {
   2174         auto* dex_cache = down_cast<mirror::DexCache*>(obj);
   2175         const auto& field_section = state->image_header_.GetImageSection(
   2176             ImageHeader::kSectionArtFields);
   2177         const auto& method_section = state->image_header_.GetMethodsSection();
   2178         size_t num_methods = dex_cache->NumResolvedMethods();
   2179         if (num_methods != 0u) {
   2180           os << "Methods (size=" << num_methods << "):\n";
   2181           ScopedIndentation indent2(&state->vios_);
   2182           auto* resolved_methods = dex_cache->GetResolvedMethods();
   2183           for (size_t i = 0, length = dex_cache->NumResolvedMethods(); i < length; ++i) {
   2184             auto* elem = mirror::DexCache::GetElementPtrSize(resolved_methods,
   2185                                                              i,
   2186                                                              image_pointer_size);
   2187             size_t run = 0;
   2188             for (size_t j = i + 1;
   2189                  j != length && elem == mirror::DexCache::GetElementPtrSize(resolved_methods,
   2190                                                                             j,
   2191                                                                             image_pointer_size);
   2192                  ++j) {
   2193               ++run;
   2194             }
   2195             if (run == 0) {
   2196               os << StringPrintf("%zd: ", i);
   2197             } else {
   2198               os << StringPrintf("%zd to %zd: ", i, i + run);
   2199               i = i + run;
   2200             }
   2201             std::string msg;
   2202             if (elem == nullptr) {
   2203               msg = "null";
   2204             } else if (method_section.Contains(
   2205                 reinterpret_cast<uint8_t*>(elem) - state->image_space_.Begin())) {
   2206               msg = reinterpret_cast<ArtMethod*>(elem)->PrettyMethod();
   2207             } else {
   2208               msg = "<not in method section>";
   2209             }
   2210             os << StringPrintf("%p   %s\n", elem, msg.c_str());
   2211           }
   2212         }
   2213         size_t num_fields = dex_cache->NumResolvedFields();
   2214         if (num_fields != 0u) {
   2215           os << "Fields (size=" << num_fields << "):\n";
   2216           ScopedIndentation indent2(&state->vios_);
   2217           auto* resolved_fields = dex_cache->GetResolvedFields();
   2218           for (size_t i = 0, length = dex_cache->NumResolvedFields(); i < length; ++i) {
   2219             auto* elem = mirror::DexCache::GetNativePairPtrSize(
   2220                 resolved_fields, i, image_pointer_size).object;
   2221             size_t run = 0;
   2222             for (size_t j = i + 1;
   2223                  j != length &&
   2224                  elem == mirror::DexCache::GetNativePairPtrSize(
   2225                      resolved_fields, j, image_pointer_size).object;
   2226                  ++j) {
   2227               ++run;
   2228             }
   2229             if (run == 0) {
   2230               os << StringPrintf("%zd: ", i);
   2231             } else {
   2232               os << StringPrintf("%zd to %zd: ", i, i + run);
   2233               i = i + run;
   2234             }
   2235             std::string msg;
   2236             if (elem == nullptr) {
   2237               msg = "null";
   2238             } else if (field_section.Contains(
   2239                 reinterpret_cast<uint8_t*>(elem) - state->image_space_.Begin())) {
   2240               msg = reinterpret_cast<ArtField*>(elem)->PrettyField();
   2241             } else {
   2242               msg = "<not in field section>";
   2243             }
   2244             os << StringPrintf("%p   %s\n", elem, msg.c_str());
   2245           }
   2246         }
   2247         size_t num_types = dex_cache->NumResolvedTypes();
   2248         if (num_types != 0u) {
   2249           os << "Types (size=" << num_types << "):\n";
   2250           ScopedIndentation indent2(&state->vios_);
   2251           auto* resolved_types = dex_cache->GetResolvedTypes();
   2252           for (size_t i = 0; i < num_types; ++i) {
   2253             auto pair = resolved_types[i].load(std::memory_order_relaxed);
   2254             size_t run = 0;
   2255             for (size_t j = i + 1; j != num_types; ++j) {
   2256               auto other_pair = resolved_types[j].load(std::memory_order_relaxed);
   2257               if (pair.index != other_pair.index ||
   2258                   pair.object.Read() != other_pair.object.Read()) {
   2259                 break;
   2260               }
   2261               ++run;
   2262             }
   2263             if (run == 0) {
   2264               os << StringPrintf("%zd: ", i);
   2265             } else {
   2266               os << StringPrintf("%zd to %zd: ", i, i + run);
   2267               i = i + run;
   2268             }
   2269             std::string msg;
   2270             auto* elem = pair.object.Read();
   2271             if (elem == nullptr) {
   2272               msg = "null";
   2273             } else {
   2274               msg = elem->PrettyClass();
   2275             }
   2276             os << StringPrintf("%p   %u %s\n", elem, pair.index, msg.c_str());
   2277           }
   2278         }
   2279       }
   2280     }
   2281     std::string temp;
   2282     state->stats_.Update(obj_class->GetDescriptor(&temp), object_bytes);
   2283   }
   2284 
   2285   void DumpMethod(ArtMethod* method, std::ostream& indent_os)
   2286       REQUIRES_SHARED(Locks::mutator_lock_) {
   2287     DCHECK(method != nullptr);
   2288     const void* quick_oat_code_begin = GetQuickOatCodeBegin(method);
   2289     const void* quick_oat_code_end = GetQuickOatCodeEnd(method);
   2290     const PointerSize pointer_size = image_header_.GetPointerSize();
   2291     OatQuickMethodHeader* method_header = reinterpret_cast<OatQuickMethodHeader*>(
   2292         reinterpret_cast<uintptr_t>(quick_oat_code_begin) - sizeof(OatQuickMethodHeader));
   2293     if (method->IsNative()) {
   2294       bool first_occurrence;
   2295       uint32_t quick_oat_code_size = GetQuickOatCodeSize(method);
   2296       ComputeOatSize(quick_oat_code_begin, &first_occurrence);
   2297       if (first_occurrence) {
   2298         stats_.native_to_managed_code_bytes += quick_oat_code_size;
   2299       }
   2300       if (quick_oat_code_begin != method->GetEntryPointFromQuickCompiledCodePtrSize(
   2301           image_header_.GetPointerSize())) {
   2302         indent_os << StringPrintf("OAT CODE: %p\n", quick_oat_code_begin);
   2303       }
   2304     } else if (method->IsAbstract() || method->IsClassInitializer()) {
   2305       // Don't print information for these.
   2306     } else if (method->IsRuntimeMethod()) {
   2307       ImtConflictTable* table = method->GetImtConflictTable(image_header_.GetPointerSize());
   2308       if (table != nullptr) {
   2309         indent_os << "IMT conflict table " << table << " method: ";
   2310         for (size_t i = 0, count = table->NumEntries(pointer_size); i < count; ++i) {
   2311           indent_os << ArtMethod::PrettyMethod(table->GetImplementationMethod(i, pointer_size))
   2312                     << " ";
   2313         }
   2314       }
   2315     } else {
   2316       const DexFile::CodeItem* code_item = method->GetCodeItem();
   2317       size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
   2318       stats_.dex_instruction_bytes += dex_instruction_bytes;
   2319 
   2320       bool first_occurrence;
   2321       size_t vmap_table_bytes = 0u;
   2322       if (!method_header->IsOptimized()) {
   2323         // Method compiled with the optimizing compiler have no vmap table.
   2324         vmap_table_bytes = ComputeOatSize(method_header->GetVmapTable(), &first_occurrence);
   2325         if (first_occurrence) {
   2326           stats_.vmap_table_bytes += vmap_table_bytes;
   2327         }
   2328       }
   2329 
   2330       uint32_t quick_oat_code_size = GetQuickOatCodeSize(method);
   2331       ComputeOatSize(quick_oat_code_begin, &first_occurrence);
   2332       if (first_occurrence) {
   2333         stats_.managed_code_bytes += quick_oat_code_size;
   2334         if (method->IsConstructor()) {
   2335           if (method->IsStatic()) {
   2336             stats_.class_initializer_code_bytes += quick_oat_code_size;
   2337           } else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
   2338             stats_.large_initializer_code_bytes += quick_oat_code_size;
   2339           }
   2340         } else if (dex_instruction_bytes > kLargeMethodDexBytes) {
   2341           stats_.large_method_code_bytes += quick_oat_code_size;
   2342         }
   2343       }
   2344       stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size;
   2345 
   2346       uint32_t method_access_flags = method->GetAccessFlags();
   2347 
   2348       indent_os << StringPrintf("OAT CODE: %p-%p\n", quick_oat_code_begin, quick_oat_code_end);
   2349       indent_os << StringPrintf("SIZE: Dex Instructions=%zd StackMaps=%zd AccessFlags=0x%x\n",
   2350                                 dex_instruction_bytes,
   2351                                 vmap_table_bytes,
   2352                                 method_access_flags);
   2353 
   2354       size_t total_size = dex_instruction_bytes +
   2355           vmap_table_bytes + quick_oat_code_size + ArtMethod::Size(image_header_.GetPointerSize());
   2356 
   2357       double expansion =
   2358       static_cast<double>(quick_oat_code_size) / static_cast<double>(dex_instruction_bytes);
   2359       stats_.ComputeOutliers(total_size, expansion, method);
   2360     }
   2361   }
   2362 
   2363   std::set<const void*> already_seen_;
   2364   // Compute the size of the given data within the oat file and whether this is the first time
   2365   // this data has been requested
   2366   size_t ComputeOatSize(const void* oat_data, bool* first_occurrence) {
   2367     if (already_seen_.count(oat_data) == 0) {
   2368       *first_occurrence = true;
   2369       already_seen_.insert(oat_data);
   2370     } else {
   2371       *first_occurrence = false;
   2372     }
   2373     return oat_dumper_->ComputeSize(oat_data);
   2374   }
   2375 
   2376  public:
   2377   struct Stats {
   2378     size_t oat_file_bytes;
   2379     size_t file_bytes;
   2380 
   2381     size_t header_bytes;
   2382     size_t object_bytes;
   2383     size_t art_field_bytes;
   2384     size_t art_method_bytes;
   2385     size_t dex_cache_arrays_bytes;
   2386     size_t interned_strings_bytes;
   2387     size_t class_table_bytes;
   2388     size_t bitmap_bytes;
   2389     size_t alignment_bytes;
   2390 
   2391     size_t managed_code_bytes;
   2392     size_t managed_code_bytes_ignoring_deduplication;
   2393     size_t native_to_managed_code_bytes;
   2394     size_t class_initializer_code_bytes;
   2395     size_t large_initializer_code_bytes;
   2396     size_t large_method_code_bytes;
   2397 
   2398     size_t vmap_table_bytes;
   2399 
   2400     size_t dex_instruction_bytes;
   2401 
   2402     std::vector<ArtMethod*> method_outlier;
   2403     std::vector<size_t> method_outlier_size;
   2404     std::vector<double> method_outlier_expansion;
   2405     std::vector<std::pair<std::string, size_t>> oat_dex_file_sizes;
   2406 
   2407     Stats()
   2408         : oat_file_bytes(0),
   2409           file_bytes(0),
   2410           header_bytes(0),
   2411           object_bytes(0),
   2412           art_field_bytes(0),
   2413           art_method_bytes(0),
   2414           dex_cache_arrays_bytes(0),
   2415           interned_strings_bytes(0),
   2416           class_table_bytes(0),
   2417           bitmap_bytes(0),
   2418           alignment_bytes(0),
   2419           managed_code_bytes(0),
   2420           managed_code_bytes_ignoring_deduplication(0),
   2421           native_to_managed_code_bytes(0),
   2422           class_initializer_code_bytes(0),
   2423           large_initializer_code_bytes(0),
   2424           large_method_code_bytes(0),
   2425           vmap_table_bytes(0),
   2426           dex_instruction_bytes(0) {}
   2427 
   2428     struct SizeAndCount {
   2429       SizeAndCount(size_t bytes_in, size_t count_in) : bytes(bytes_in), count(count_in) {}
   2430       size_t bytes;
   2431       size_t count;
   2432     };
   2433     typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable;
   2434     SizeAndCountTable sizes_and_counts;
   2435 
   2436     void Update(const char* descriptor, size_t object_bytes_in) {
   2437       SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor);
   2438       if (it != sizes_and_counts.end()) {
   2439         it->second.bytes += object_bytes_in;
   2440         it->second.count += 1;
   2441       } else {
   2442         sizes_and_counts.Put(descriptor, SizeAndCount(object_bytes_in, 1));
   2443       }
   2444     }
   2445 
   2446     double PercentOfOatBytes(size_t size) {
   2447       return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100;
   2448     }
   2449 
   2450     double PercentOfFileBytes(size_t size) {
   2451       return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
   2452     }
   2453 
   2454     double PercentOfObjectBytes(size_t size) {
   2455       return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
   2456     }
   2457 
   2458     void ComputeOutliers(size_t total_size, double expansion, ArtMethod* method) {
   2459       method_outlier_size.push_back(total_size);
   2460       method_outlier_expansion.push_back(expansion);
   2461       method_outlier.push_back(method);
   2462     }
   2463 
   2464     void DumpOutliers(std::ostream& os)
   2465         REQUIRES_SHARED(Locks::mutator_lock_) {
   2466       size_t sum_of_sizes = 0;
   2467       size_t sum_of_sizes_squared = 0;
   2468       size_t sum_of_expansion = 0;
   2469       size_t sum_of_expansion_squared = 0;
   2470       size_t n = method_outlier_size.size();
   2471       if (n <= 1) {
   2472         return;
   2473       }
   2474       for (size_t i = 0; i < n; i++) {
   2475         size_t cur_size = method_outlier_size[i];
   2476         sum_of_sizes += cur_size;
   2477         sum_of_sizes_squared += cur_size * cur_size;
   2478         double cur_expansion = method_outlier_expansion[i];
   2479         sum_of_expansion += cur_expansion;
   2480         sum_of_expansion_squared += cur_expansion * cur_expansion;
   2481       }
   2482       size_t size_mean = sum_of_sizes / n;
   2483       size_t size_variance = (sum_of_sizes_squared - sum_of_sizes * size_mean) / (n - 1);
   2484       double expansion_mean = sum_of_expansion / n;
   2485       double expansion_variance =
   2486           (sum_of_expansion_squared - sum_of_expansion * expansion_mean) / (n - 1);
   2487 
   2488       // Dump methods whose size is a certain number of standard deviations from the mean
   2489       size_t dumped_values = 0;
   2490       size_t skipped_values = 0;
   2491       for (size_t i = 100; i > 0; i--) {  // i is the current number of standard deviations
   2492         size_t cur_size_variance = i * i * size_variance;
   2493         bool first = true;
   2494         for (size_t j = 0; j < n; j++) {
   2495           size_t cur_size = method_outlier_size[j];
   2496           if (cur_size > size_mean) {
   2497             size_t cur_var = cur_size - size_mean;
   2498             cur_var = cur_var * cur_var;
   2499             if (cur_var > cur_size_variance) {
   2500               if (dumped_values > 20) {
   2501                 if (i == 1) {
   2502                   skipped_values++;
   2503                 } else {
   2504                   i = 2;  // jump to counting for 1 standard deviation
   2505                   break;
   2506                 }
   2507               } else {
   2508                 if (first) {
   2509                   os << "\nBig methods (size > " << i << " standard deviations the norm):\n";
   2510                   first = false;
   2511                 }
   2512                 os << ArtMethod::PrettyMethod(method_outlier[j]) << " requires storage of "
   2513                     << PrettySize(cur_size) << "\n";
   2514                 method_outlier_size[j] = 0;  // don't consider this method again
   2515                 dumped_values++;
   2516               }
   2517             }
   2518           }
   2519         }
   2520       }
   2521       if (skipped_values > 0) {
   2522         os << "... skipped " << skipped_values
   2523            << " methods with size > 1 standard deviation from the norm\n";
   2524       }
   2525       os << std::flush;
   2526 
   2527       // Dump methods whose expansion is a certain number of standard deviations from the mean
   2528       dumped_values = 0;
   2529       skipped_values = 0;
   2530       for (size_t i = 10; i > 0; i--) {  // i is the current number of standard deviations
   2531         double cur_expansion_variance = i * i * expansion_variance;
   2532         bool first = true;
   2533         for (size_t j = 0; j < n; j++) {
   2534           double cur_expansion = method_outlier_expansion[j];
   2535           if (cur_expansion > expansion_mean) {
   2536             size_t cur_var = cur_expansion - expansion_mean;
   2537             cur_var = cur_var * cur_var;
   2538             if (cur_var > cur_expansion_variance) {
   2539               if (dumped_values > 20) {
   2540                 if (i == 1) {
   2541                   skipped_values++;
   2542                 } else {
   2543                   i = 2;  // jump to counting for 1 standard deviation
   2544                   break;
   2545                 }
   2546               } else {
   2547                 if (first) {
   2548                   os << "\nLarge expansion methods (size > " << i
   2549                       << " standard deviations the norm):\n";
   2550                   first = false;
   2551                 }
   2552                 os << ArtMethod::PrettyMethod(method_outlier[j]) << " expanded code by "
   2553                    << cur_expansion << "\n";
   2554                 method_outlier_expansion[j] = 0.0;  // don't consider this method again
   2555                 dumped_values++;
   2556               }
   2557             }
   2558           }
   2559         }
   2560       }
   2561       if (skipped_values > 0) {
   2562         os << "... skipped " << skipped_values
   2563            << " methods with expansion > 1 standard deviation from the norm\n";
   2564       }
   2565       os << "\n" << std::flush;
   2566     }
   2567 
   2568     void Dump(std::ostream& os, std::ostream& indent_os)
   2569         REQUIRES_SHARED(Locks::mutator_lock_) {
   2570       {
   2571         os << "art_file_bytes = " << PrettySize(file_bytes) << "\n\n"
   2572            << "art_file_bytes = header_bytes + object_bytes + alignment_bytes\n";
   2573         indent_os << StringPrintf("header_bytes           =  %8zd (%2.0f%% of art file bytes)\n"
   2574                                   "object_bytes           =  %8zd (%2.0f%% of art file bytes)\n"
   2575                                   "art_field_bytes        =  %8zd (%2.0f%% of art file bytes)\n"
   2576                                   "art_method_bytes       =  %8zd (%2.0f%% of art file bytes)\n"
   2577                                   "dex_cache_arrays_bytes =  %8zd (%2.0f%% of art file bytes)\n"
   2578                                   "interned_string_bytes  =  %8zd (%2.0f%% of art file bytes)\n"
   2579                                   "class_table_bytes      =  %8zd (%2.0f%% of art file bytes)\n"
   2580                                   "bitmap_bytes           =  %8zd (%2.0f%% of art file bytes)\n"
   2581                                   "alignment_bytes        =  %8zd (%2.0f%% of art file bytes)\n\n",
   2582                                   header_bytes, PercentOfFileBytes(header_bytes),
   2583                                   object_bytes, PercentOfFileBytes(object_bytes),
   2584                                   art_field_bytes, PercentOfFileBytes(art_field_bytes),
   2585                                   art_method_bytes, PercentOfFileBytes(art_method_bytes),
   2586                                   dex_cache_arrays_bytes,
   2587                                   PercentOfFileBytes(dex_cache_arrays_bytes),
   2588                                   interned_strings_bytes,
   2589                                   PercentOfFileBytes(interned_strings_bytes),
   2590                                   class_table_bytes, PercentOfFileBytes(class_table_bytes),
   2591                                   bitmap_bytes, PercentOfFileBytes(bitmap_bytes),
   2592                                   alignment_bytes, PercentOfFileBytes(alignment_bytes))
   2593             << std::flush;
   2594         CHECK_EQ(file_bytes,
   2595                  header_bytes + object_bytes + art_field_bytes + art_method_bytes +
   2596                  dex_cache_arrays_bytes + interned_strings_bytes + class_table_bytes +
   2597                  bitmap_bytes + alignment_bytes);
   2598       }
   2599 
   2600       os << "object_bytes breakdown:\n";
   2601       size_t object_bytes_total = 0;
   2602       for (const auto& sizes_and_count : sizes_and_counts) {
   2603         const std::string& descriptor(sizes_and_count.first);
   2604         double average = static_cast<double>(sizes_and_count.second.bytes) /
   2605             static_cast<double>(sizes_and_count.second.count);
   2606         double percent = PercentOfObjectBytes(sizes_and_count.second.bytes);
   2607         os << StringPrintf("%32s %8zd bytes %6zd instances "
   2608                            "(%4.0f bytes/instance) %2.0f%% of object_bytes\n",
   2609                            descriptor.c_str(), sizes_and_count.second.bytes,
   2610                            sizes_and_count.second.count, average, percent);
   2611         object_bytes_total += sizes_and_count.second.bytes;
   2612       }
   2613       os << "\n" << std::flush;
   2614       CHECK_EQ(object_bytes, object_bytes_total);
   2615 
   2616       os << StringPrintf("oat_file_bytes               = %8zd\n"
   2617                          "managed_code_bytes           = %8zd (%2.0f%% of oat file bytes)\n"
   2618                          "native_to_managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n\n"
   2619                          "class_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
   2620                          "large_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
   2621                          "large_method_code_bytes      = %8zd (%2.0f%% of oat file bytes)\n\n",
   2622                          oat_file_bytes,
   2623                          managed_code_bytes,
   2624                          PercentOfOatBytes(managed_code_bytes),
   2625                          native_to_managed_code_bytes,
   2626                          PercentOfOatBytes(native_to_managed_code_bytes),
   2627                          class_initializer_code_bytes,
   2628                          PercentOfOatBytes(class_initializer_code_bytes),
   2629                          large_initializer_code_bytes,
   2630                          PercentOfOatBytes(large_initializer_code_bytes),
   2631                          large_method_code_bytes,
   2632                          PercentOfOatBytes(large_method_code_bytes))
   2633             << "DexFile sizes:\n";
   2634       for (const std::pair<std::string, size_t>& oat_dex_file_size : oat_dex_file_sizes) {
   2635         os << StringPrintf("%s = %zd (%2.0f%% of oat file bytes)\n",
   2636                            oat_dex_file_size.first.c_str(), oat_dex_file_size.second,
   2637                            PercentOfOatBytes(oat_dex_file_size.second));
   2638       }
   2639 
   2640       os << "\n" << StringPrintf("vmap_table_bytes       = %7zd (%2.0f%% of oat file bytes)\n\n",
   2641                                  vmap_table_bytes, PercentOfOatBytes(vmap_table_bytes))
   2642          << std::flush;
   2643 
   2644       os << StringPrintf("dex_instruction_bytes = %zd\n", dex_instruction_bytes)
   2645          << StringPrintf("managed_code_bytes expansion = %.2f (ignoring deduplication %.2f)\n\n",
   2646                          static_cast<double>(managed_code_bytes) /
   2647                              static_cast<double>(dex_instruction_bytes),
   2648                          static_cast<double>(managed_code_bytes_ignoring_deduplication) /
   2649                              static_cast<double>(dex_instruction_bytes))
   2650          << std::flush;
   2651 
   2652       DumpOutliers(os);
   2653     }
   2654   } stats_;
   2655 
   2656  private:
   2657   enum {
   2658     // Number of bytes for a constructor to be considered large. Based on the 1000 basic block
   2659     // threshold, we assume 2 bytes per instruction and 2 instructions per block.
   2660     kLargeConstructorDexBytes = 4000,
   2661     // Number of bytes for a method to be considered large. Based on the 4000 basic block
   2662     // threshold, we assume 2 bytes per instruction and 2 instructions per block.
   2663     kLargeMethodDexBytes = 16000
   2664   };
   2665 
   2666   // For performance, use the *os_ directly for anything that doesn't need indentation
   2667   // and prepare an indentation stream with default indentation 1.
   2668   std::ostream* os_;
   2669   VariableIndentationOutputStream vios_;
   2670   ScopedIndentation indent1_;
   2671 
   2672   gc::space::ImageSpace& image_space_;
   2673   const ImageHeader& image_header_;
   2674   std::unique_ptr<OatDumper> oat_dumper_;
   2675   OatDumperOptions* oat_dumper_options_;
   2676   std::set<mirror::Object*> dex_caches_;
   2677 
   2678   DISALLOW_COPY_AND_ASSIGN(ImageDumper);
   2679 };
   2680 
   2681 static int DumpImage(gc::space::ImageSpace* image_space,
   2682                      OatDumperOptions* options,
   2683                      std::ostream* os) REQUIRES_SHARED(Locks::mutator_lock_) {
   2684   const ImageHeader& image_header = image_space->GetImageHeader();
   2685   if (!image_header.IsValid()) {
   2686     fprintf(stderr, "Invalid image header %s\n", image_space->GetImageLocation().c_str());
   2687     return EXIT_FAILURE;
   2688   }
   2689   ImageDumper image_dumper(os, *image_space, image_header, options);
   2690   if (!image_dumper.Dump()) {
   2691     return EXIT_FAILURE;
   2692   }
   2693   return EXIT_SUCCESS;
   2694 }
   2695 
   2696 static int DumpImages(Runtime* runtime, OatDumperOptions* options, std::ostream* os) {
   2697   // Dumping the image, no explicit class loader.
   2698   ScopedNullHandle<mirror::ClassLoader> null_class_loader;
   2699   options->class_loader_ = &null_class_loader;
   2700 
   2701   ScopedObjectAccess soa(Thread::Current());
   2702   if (options->app_image_ != nullptr) {
   2703     if (options->app_oat_ == nullptr) {
   2704       LOG(ERROR) << "Can not dump app image without app oat file";
   2705       return EXIT_FAILURE;
   2706     }
   2707     // We can't know if the app image is 32 bits yet, but it contains pointers into the oat file.
   2708     // We need to map the oat file in the low 4gb or else the fixup wont be able to fit oat file
   2709     // pointers into 32 bit pointer sized ArtMethods.
   2710     std::string error_msg;
   2711     std::unique_ptr<OatFile> oat_file(OatFile::Open(options->app_oat_,
   2712                                                     options->app_oat_,
   2713                                                     nullptr,
   2714                                                     nullptr,
   2715                                                     false,
   2716                                                     /*low_4gb*/true,
   2717                                                     nullptr,
   2718                                                     &error_msg));
   2719     if (oat_file == nullptr) {
   2720       LOG(ERROR) << "Failed to open oat file " << options->app_oat_ << " with error " << error_msg;
   2721       return EXIT_FAILURE;
   2722     }
   2723     std::unique_ptr<gc::space::ImageSpace> space(
   2724         gc::space::ImageSpace::CreateFromAppImage(options->app_image_, oat_file.get(), &error_msg));
   2725     if (space == nullptr) {
   2726       LOG(ERROR) << "Failed to open app image " << options->app_image_ << " with error "
   2727                  << error_msg;
   2728     }
   2729     // Open dex files for the image.
   2730     std::vector<std::unique_ptr<const DexFile>> dex_files;
   2731     if (!runtime->GetClassLinker()->OpenImageDexFiles(space.get(), &dex_files, &error_msg)) {
   2732       LOG(ERROR) << "Failed to open app image dex files " << options->app_image_ << " with error "
   2733                  << error_msg;
   2734     }
   2735     // Dump the actual image.
   2736     int result = DumpImage(space.get(), options, os);
   2737     if (result != EXIT_SUCCESS) {
   2738       return result;
   2739     }
   2740     // Fall through to dump the boot images.
   2741   }
   2742 
   2743   gc::Heap* heap = runtime->GetHeap();
   2744   CHECK(heap->HasBootImageSpace()) << "No image spaces";
   2745   for (gc::space::ImageSpace* image_space : heap->GetBootImageSpaces()) {
   2746     int result = DumpImage(image_space, options, os);
   2747     if (result != EXIT_SUCCESS) {
   2748       return result;
   2749     }
   2750   }
   2751   return EXIT_SUCCESS;
   2752 }
   2753 
   2754 static jobject InstallOatFile(Runtime* runtime,
   2755                               std::unique_ptr<OatFile> oat_file,
   2756                               std::vector<const DexFile*>* class_path)
   2757     REQUIRES_SHARED(Locks::mutator_lock_) {
   2758   Thread* self = Thread::Current();
   2759   CHECK(self != nullptr);
   2760   // Need well-known-classes.
   2761   WellKnownClasses::Init(self->GetJniEnv());
   2762 
   2763   // Need to register dex files to get a working dex cache.
   2764   OatFile* oat_file_ptr = oat_file.get();
   2765   ClassLinker* class_linker = runtime->GetClassLinker();
   2766   runtime->GetOatFileManager().RegisterOatFile(std::move(oat_file));
   2767   for (const OatFile::OatDexFile* odf : oat_file_ptr->GetOatDexFiles()) {
   2768     std::string error_msg;
   2769     const DexFile* const dex_file = OpenDexFile(odf, &error_msg);
   2770     CHECK(dex_file != nullptr) << error_msg;
   2771     ObjPtr<mirror::DexCache> dex_cache =
   2772         class_linker->RegisterDexFile(*dex_file, nullptr);
   2773     CHECK(dex_cache != nullptr);
   2774     class_path->push_back(dex_file);
   2775   }
   2776 
   2777   // Need a class loader. Fake that we're a compiler.
   2778   // Note: this will run initializers through the unstarted runtime, so make sure it's
   2779   //       initialized.
   2780   interpreter::UnstartedRuntime::Initialize();
   2781 
   2782   jobject class_loader = class_linker->CreatePathClassLoader(self, *class_path);
   2783 
   2784   return class_loader;
   2785 }
   2786 
   2787 static int DumpOatWithRuntime(Runtime* runtime,
   2788                               std::unique_ptr<OatFile> oat_file,
   2789                               OatDumperOptions* options,
   2790                               std::ostream* os) {
   2791   CHECK(runtime != nullptr && oat_file != nullptr && options != nullptr);
   2792   ScopedObjectAccess soa(Thread::Current());
   2793 
   2794   OatFile* oat_file_ptr = oat_file.get();
   2795   std::vector<const DexFile*> class_path;
   2796   jobject class_loader = InstallOatFile(runtime, std::move(oat_file), &class_path);
   2797 
   2798   // Use the class loader while dumping.
   2799   StackHandleScope<1> scope(soa.Self());
   2800   Handle<mirror::ClassLoader> loader_handle = scope.NewHandle(
   2801       soa.Decode<mirror::ClassLoader>(class_loader));
   2802   options->class_loader_ = &loader_handle;
   2803 
   2804   OatDumper oat_dumper(*oat_file_ptr, *options);
   2805   bool success = oat_dumper.Dump(*os);
   2806   return (success) ? EXIT_SUCCESS : EXIT_FAILURE;
   2807 }
   2808 
   2809 static int DumpOatWithoutRuntime(OatFile* oat_file, OatDumperOptions* options, std::ostream* os) {
   2810   CHECK(oat_file != nullptr && options != nullptr);
   2811   // No image = no class loader.
   2812   ScopedNullHandle<mirror::ClassLoader> null_class_loader;
   2813   options->class_loader_ = &null_class_loader;
   2814 
   2815   OatDumper oat_dumper(*oat_file, *options);
   2816   bool success = oat_dumper.Dump(*os);
   2817   return (success) ? EXIT_SUCCESS : EXIT_FAILURE;
   2818 }
   2819 
   2820 static int DumpOat(Runtime* runtime, const char* oat_filename, OatDumperOptions* options,
   2821                    std::ostream* os) {
   2822   std::string error_msg;
   2823   std::unique_ptr<OatFile> oat_file(OatFile::Open(oat_filename,
   2824                                                   oat_filename,
   2825                                                   nullptr,
   2826                                                   nullptr,
   2827                                                   false,
   2828                                                   /*low_4gb*/false,
   2829                                                   nullptr,
   2830                                                   &error_msg));
   2831   if (oat_file == nullptr) {
   2832     fprintf(stderr, "Failed to open oat file from '%s': %s\n", oat_filename, error_msg.c_str());
   2833     return EXIT_FAILURE;
   2834   }
   2835 
   2836   if (runtime != nullptr) {
   2837     return DumpOatWithRuntime(runtime, std::move(oat_file), options, os);
   2838   } else {
   2839     return DumpOatWithoutRuntime(oat_file.get(), options, os);
   2840   }
   2841 }
   2842 
   2843 static int SymbolizeOat(const char* oat_filename, std::string& output_name, bool no_bits) {
   2844   std::string error_msg;
   2845   OatFile* oat_file = OatFile::Open(oat_filename,
   2846                                     oat_filename,
   2847                                     nullptr,
   2848                                     nullptr,
   2849                                     false,
   2850                                     /*low_4gb*/false,
   2851                                     nullptr,
   2852                                     &error_msg);
   2853   if (oat_file == nullptr) {
   2854     fprintf(stderr, "Failed to open oat file from '%s': %s\n", oat_filename, error_msg.c_str());
   2855     return EXIT_FAILURE;
   2856   }
   2857 
   2858   bool result;
   2859   // Try to produce an ELF file of the same type. This is finicky, as we have used 32-bit ELF
   2860   // files for 64-bit code in the past.
   2861   if (Is64BitInstructionSet(oat_file->GetOatHeader().GetInstructionSet())) {
   2862     OatSymbolizer<ElfTypes64> oat_symbolizer(oat_file, output_name, no_bits);
   2863     result = oat_symbolizer.Symbolize();
   2864   } else {
   2865     OatSymbolizer<ElfTypes32> oat_symbolizer(oat_file, output_name, no_bits);
   2866     result = oat_symbolizer.Symbolize();
   2867   }
   2868   if (!result) {
   2869     fprintf(stderr, "Failed to symbolize\n");
   2870     return EXIT_FAILURE;
   2871   }
   2872 
   2873   return EXIT_SUCCESS;
   2874 }
   2875 
   2876 class IMTDumper {
   2877  public:
   2878   static bool Dump(Runtime* runtime,
   2879                    const std::string& imt_file,
   2880                    bool dump_imt_stats,
   2881                    const char* oat_filename) {
   2882     Thread* self = Thread::Current();
   2883 
   2884     ScopedObjectAccess soa(self);
   2885     StackHandleScope<1> scope(self);
   2886     MutableHandle<mirror::ClassLoader> class_loader = scope.NewHandle<mirror::ClassLoader>(nullptr);
   2887     std::vector<const DexFile*> class_path;
   2888 
   2889     if (oat_filename != nullptr) {
   2890       std::string error_msg;
   2891       std::unique_ptr<OatFile> oat_file(OatFile::Open(oat_filename,
   2892                                                       oat_filename,
   2893                                                       nullptr,
   2894                                                       nullptr,
   2895                                                       false,
   2896                                                       /*low_4gb*/false,
   2897                                                       nullptr,
   2898                                                       &error_msg));
   2899       if (oat_file == nullptr) {
   2900         fprintf(stderr, "Failed to open oat file from '%s': %s\n", oat_filename, error_msg.c_str());
   2901         return false;
   2902       }
   2903 
   2904       class_loader.Assign(soa.Decode<mirror::ClassLoader>(
   2905           InstallOatFile(runtime, std::move(oat_file), &class_path)));
   2906     } else {
   2907       class_loader.Assign(nullptr);  // Boot classloader. Just here for explicit documentation.
   2908       class_path = runtime->GetClassLinker()->GetBootClassPath();
   2909     }
   2910 
   2911     if (!imt_file.empty()) {
   2912       return DumpImt(runtime, imt_file, class_loader);
   2913     }
   2914 
   2915     if (dump_imt_stats) {
   2916       return DumpImtStats(runtime, class_path, class_loader);
   2917     }
   2918 
   2919     LOG(FATAL) << "Should not reach here";
   2920     UNREACHABLE();
   2921   }
   2922 
   2923  private:
   2924   static bool DumpImt(Runtime* runtime,
   2925                       const std::string& imt_file,
   2926                       Handle<mirror::ClassLoader> h_class_loader)
   2927       REQUIRES_SHARED(Locks::mutator_lock_) {
   2928     std::vector<std::string> lines = ReadCommentedInputFromFile(imt_file);
   2929     std::unordered_set<std::string> prepared;
   2930 
   2931     for (const std::string& line : lines) {
   2932       // A line should be either a class descriptor, in which case we will dump the complete IMT,
   2933       // or a class descriptor and an interface method, in which case we will lookup the method,
   2934       // determine its IMT slot, and check the class' IMT.
   2935       size_t first_space = line.find(' ');
   2936       if (first_space == std::string::npos) {
   2937         DumpIMTForClass(runtime, line, h_class_loader, &prepared);
   2938       } else {
   2939         DumpIMTForMethod(runtime,
   2940                          line.substr(0, first_space),
   2941                          line.substr(first_space + 1, std::string::npos),
   2942                          h_class_loader,
   2943                          &prepared);
   2944       }
   2945       std::cerr << std::endl;
   2946     }
   2947 
   2948     return true;
   2949   }
   2950 
   2951   static bool DumpImtStats(Runtime* runtime,
   2952                            const std::vector<const DexFile*>& dex_files,
   2953                            Handle<mirror::ClassLoader> h_class_loader)
   2954       REQUIRES_SHARED(Locks::mutator_lock_) {
   2955     size_t without_imt = 0;
   2956     size_t with_imt = 0;
   2957     std::map<size_t, size_t> histogram;
   2958 
   2959     ClassLinker* class_linker = runtime->GetClassLinker();
   2960     const PointerSize pointer_size = class_linker->GetImagePointerSize();
   2961     std::unordered_set<std::string> prepared;
   2962 
   2963     Thread* self = Thread::Current();
   2964     StackHandleScope<1> scope(self);
   2965     MutableHandle<mirror::Class> h_klass(scope.NewHandle<mirror::Class>(nullptr));
   2966 
   2967     for (const DexFile* dex_file : dex_files) {
   2968       for (uint32_t class_def_index = 0;
   2969            class_def_index != dex_file->NumClassDefs();
   2970            ++class_def_index) {
   2971         const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
   2972         const char* descriptor = dex_file->GetClassDescriptor(class_def);
   2973         h_klass.Assign(class_linker->FindClass(self, descriptor, h_class_loader));
   2974         if (h_klass == nullptr) {
   2975           std::cerr << "Warning: could not load " << descriptor << std::endl;
   2976           continue;
   2977         }
   2978 
   2979         if (HasNoIMT(runtime, h_klass, pointer_size, &prepared)) {
   2980           without_imt++;
   2981           continue;
   2982         }
   2983 
   2984         ImTable* im_table = PrepareAndGetImTable(runtime, h_klass, pointer_size, &prepared);
   2985         if (im_table == nullptr) {
   2986           // Should not happen, but accept.
   2987           without_imt++;
   2988           continue;
   2989         }
   2990 
   2991         with_imt++;
   2992         for (size_t imt_index = 0; imt_index != ImTable::kSize; ++imt_index) {
   2993           ArtMethod* ptr = im_table->Get(imt_index, pointer_size);
   2994           if (ptr->IsRuntimeMethod()) {
   2995             if (ptr->IsImtUnimplementedMethod()) {
   2996               histogram[0]++;
   2997             } else {
   2998               ImtConflictTable* current_table = ptr->GetImtConflictTable(pointer_size);
   2999               histogram[current_table->NumEntries(pointer_size)]++;
   3000             }
   3001           } else {
   3002             histogram[1]++;
   3003           }
   3004         }
   3005       }
   3006     }
   3007 
   3008     std::cerr << "IMT stats:"
   3009               << std::endl << std::endl;
   3010 
   3011     std::cerr << "  " << with_imt << " classes with IMT."
   3012               << std::endl << std::endl;
   3013     std::cerr << "  " << without_imt << " classes without IMT (or copy from Object)."
   3014               << std::endl << std::endl;
   3015 
   3016     double sum_one = 0;
   3017     size_t count_one = 0;
   3018 
   3019     std::cerr << "  " << "IMT histogram" << std::endl;
   3020     for (auto& bucket : histogram) {
   3021       std::cerr << "    " << bucket.first << " " << bucket.second << std::endl;
   3022       if (bucket.first > 0) {
   3023         sum_one += bucket.second * bucket.first;
   3024         count_one += bucket.second;
   3025       }
   3026     }
   3027 
   3028     double count_zero = count_one + histogram[0];
   3029     std::cerr << "   Stats:" << std::endl;
   3030     std::cerr << "     Average depth (including empty): " << (sum_one / count_zero) << std::endl;
   3031     std::cerr << "     Average depth (excluding empty): " << (sum_one / count_one) << std::endl;
   3032 
   3033     return true;
   3034   }
   3035 
   3036   // Return whether the given class has no IMT (or the one shared with java.lang.Object).
   3037   static bool HasNoIMT(Runtime* runtime,
   3038                        Handle<mirror::Class> klass,
   3039                        const PointerSize pointer_size,
   3040                        std::unordered_set<std::string>* prepared)
   3041       REQUIRES_SHARED(Locks::mutator_lock_) {
   3042     if (klass->IsObjectClass() || !klass->ShouldHaveImt()) {
   3043       return true;
   3044     }
   3045 
   3046     if (klass->GetImt(pointer_size) == nullptr) {
   3047       PrepareClass(runtime, klass, prepared);
   3048     }
   3049 
   3050     mirror::Class* object_class = mirror::Class::GetJavaLangClass()->GetSuperClass();
   3051     DCHECK(object_class->IsObjectClass());
   3052 
   3053     bool result = klass->GetImt(pointer_size) == object_class->GetImt(pointer_size);
   3054 
   3055     if (klass->GetIfTable()->Count() == 0) {
   3056       DCHECK(result);
   3057     }
   3058 
   3059     return result;
   3060   }
   3061 
   3062   static void PrintTable(ImtConflictTable* table, PointerSize pointer_size)
   3063       REQUIRES_SHARED(Locks::mutator_lock_) {
   3064     if (table == nullptr) {
   3065       std::cerr << "    <No IMT?>" << std::endl;
   3066       return;
   3067     }
   3068     size_t table_index = 0;
   3069     for (;;) {
   3070       ArtMethod* ptr = table->GetInterfaceMethod(table_index, pointer_size);
   3071       if (ptr == nullptr) {
   3072         return;
   3073       }
   3074       table_index++;
   3075       std::cerr << "    " << ptr->PrettyMethod(true) << std::endl;
   3076     }
   3077   }
   3078 
   3079   static ImTable* PrepareAndGetImTable(Runtime* runtime,
   3080                                        Thread* self,
   3081                                        Handle<mirror::ClassLoader> h_loader,
   3082                                        const std::string& class_name,
   3083                                        const PointerSize pointer_size,
   3084                                        mirror::Class** klass_out,
   3085                                        std::unordered_set<std::string>* prepared)
   3086       REQUIRES_SHARED(Locks::mutator_lock_) {
   3087     if (class_name.empty()) {
   3088       return nullptr;
   3089     }
   3090 
   3091     std::string descriptor;
   3092     if (class_name[0] == 'L') {
   3093       descriptor = class_name;
   3094     } else {
   3095       descriptor = DotToDescriptor(class_name.c_str());
   3096     }
   3097 
   3098     mirror::Class* klass = runtime->GetClassLinker()->FindClass(self, descriptor.c_str(), h_loader);
   3099 
   3100     if (klass == nullptr) {
   3101       self->ClearException();
   3102       std::cerr << "Did not find " <<  class_name << std::endl;
   3103       *klass_out = nullptr;
   3104       return nullptr;
   3105     }
   3106 
   3107     StackHandleScope<1> scope(Thread::Current());
   3108     Handle<mirror::Class> h_klass = scope.NewHandle<mirror::Class>(klass);
   3109 
   3110     ImTable* ret = PrepareAndGetImTable(runtime, h_klass, pointer_size, prepared);
   3111     *klass_out = h_klass.Get();
   3112     return ret;
   3113   }
   3114 
   3115   static ImTable* PrepareAndGetImTable(Runtime* runtime,
   3116                                        Handle<mirror::Class> h_klass,
   3117                                        const PointerSize pointer_size,
   3118                                        std::unordered_set<std::string>* prepared)
   3119       REQUIRES_SHARED(Locks::mutator_lock_) {
   3120     PrepareClass(runtime, h_klass, prepared);
   3121     return h_klass->GetImt(pointer_size);
   3122   }
   3123 
   3124   static void DumpIMTForClass(Runtime* runtime,
   3125                               const std::string& class_name,
   3126                               Handle<mirror::ClassLoader> h_loader,
   3127                               std::unordered_set<std::string>* prepared)
   3128       REQUIRES_SHARED(Locks::mutator_lock_) {
   3129     const PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
   3130     mirror::Class* klass;
   3131     ImTable* imt = PrepareAndGetImTable(runtime,
   3132                                         Thread::Current(),
   3133                                         h_loader,
   3134                                         class_name,
   3135                                         pointer_size,
   3136                                         &klass,
   3137                                         prepared);
   3138     if (imt == nullptr) {
   3139       return;
   3140     }
   3141 
   3142     std::cerr << class_name << std::endl << " IMT:" << std::endl;
   3143     for (size_t index = 0; index < ImTable::kSize; ++index) {
   3144       std::cerr << "  " << index << ":" << std::endl;
   3145       ArtMethod* ptr = imt->Get(index, pointer_size);
   3146       if (ptr->IsRuntimeMethod()) {
   3147         if (ptr->IsImtUnimplementedMethod()) {
   3148           std::cerr << "    <empty>" << std::endl;
   3149         } else {
   3150           ImtConflictTable* current_table = ptr->GetImtConflictTable(pointer_size);
   3151           PrintTable(current_table, pointer_size);
   3152         }
   3153       } else {
   3154         std::cerr << "    " << ptr->PrettyMethod(true) << std::endl;
   3155       }
   3156     }
   3157 
   3158     std::cerr << " Interfaces:" << std::endl;
   3159     // Run through iftable, find methods that slot here, see if they fit.
   3160     mirror::IfTable* if_table = klass->GetIfTable();
   3161     for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
   3162       mirror::Class* iface = if_table->GetInterface(i);
   3163       std::string iface_name;
   3164       std::cerr << "  " << iface->GetDescriptor(&iface_name) << std::endl;
   3165 
   3166       for (ArtMethod& iface_method : iface->GetVirtualMethods(pointer_size)) {
   3167         uint32_t class_hash, name_hash, signature_hash;
   3168         ImTable::GetImtHashComponents(&iface_method, &class_hash, &name_hash, &signature_hash);
   3169         uint32_t imt_slot = ImTable::GetImtIndex(&iface_method);
   3170         std::cerr << "    " << iface_method.PrettyMethod(true)
   3171             << " slot=" << imt_slot
   3172             << std::hex
   3173             << " class_hash=0x" << class_hash
   3174             << " name_hash=0x" << name_hash
   3175             << " signature_hash=0x" << signature_hash
   3176             << std::dec
   3177             << std::endl;
   3178       }
   3179     }
   3180   }
   3181 
   3182   static void DumpIMTForMethod(Runtime* runtime,
   3183                                const std::string& class_name,
   3184                                const std::string& method,
   3185                                Handle<mirror::ClassLoader> h_loader,
   3186                                std::unordered_set<std::string>* prepared)
   3187       REQUIRES_SHARED(Locks::mutator_lock_) {
   3188     const PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
   3189     mirror::Class* klass;
   3190     ImTable* imt = PrepareAndGetImTable(runtime,
   3191                                         Thread::Current(),
   3192                                         h_loader,
   3193                                         class_name,
   3194                                         pointer_size,
   3195                                         &klass,
   3196                                         prepared);
   3197     if (imt == nullptr) {
   3198       return;
   3199     }
   3200 
   3201     std::cerr << class_name << " <" << method << ">" << std::endl;
   3202     for (size_t index = 0; index < ImTable::kSize; ++index) {
   3203       ArtMethod* ptr = imt->Get(index, pointer_size);
   3204       if (ptr->IsRuntimeMethod()) {
   3205         if (ptr->IsImtUnimplementedMethod()) {
   3206           continue;
   3207         }
   3208 
   3209         ImtConflictTable* current_table = ptr->GetImtConflictTable(pointer_size);
   3210         if (current_table == nullptr) {
   3211           continue;
   3212         }
   3213 
   3214         size_t table_index = 0;
   3215         for (;;) {
   3216           ArtMethod* ptr2 = current_table->GetInterfaceMethod(table_index, pointer_size);
   3217           if (ptr2 == nullptr) {
   3218             break;
   3219           }
   3220           table_index++;
   3221 
   3222           std::string p_name = ptr2->PrettyMethod(true);
   3223           if (android::base::StartsWith(p_name, method.c_str())) {
   3224             std::cerr << "  Slot "
   3225                       << index
   3226                       << " ("
   3227                       << current_table->NumEntries(pointer_size)
   3228                       << ")"
   3229                       << std::endl;
   3230             PrintTable(current_table, pointer_size);
   3231             return;
   3232           }
   3233         }
   3234       } else {
   3235         std::string p_name = ptr->PrettyMethod(true);
   3236         if (android::base::StartsWith(p_name, method.c_str())) {
   3237           std::cerr << "  Slot " << index << " (1)" << std::endl;
   3238           std::cerr << "    " << p_name << std::endl;
   3239         } else {
   3240           // Run through iftable, find methods that slot here, see if they fit.
   3241           mirror::IfTable* if_table = klass->GetIfTable();
   3242           for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
   3243             mirror::Class* iface = if_table->GetInterface(i);
   3244             size_t num_methods = iface->NumDeclaredVirtualMethods();
   3245             if (num_methods > 0) {
   3246               for (ArtMethod& iface_method : iface->GetMethods(pointer_size)) {
   3247                 if (ImTable::GetImtIndex(&iface_method) == index) {
   3248                   std::string i_name = iface_method.PrettyMethod(true);
   3249                   if (android::base::StartsWith(i_name, method.c_str())) {
   3250                     std::cerr << "  Slot " << index << " (1)" << std::endl;
   3251                     std::cerr << "    " << p_name << " (" << i_name << ")" << std::endl;
   3252                   }
   3253                 }
   3254               }
   3255             }
   3256           }
   3257         }
   3258       }
   3259     }
   3260   }
   3261 
   3262   // Read lines from the given stream, dropping comments and empty lines
   3263   static std::vector<std::string> ReadCommentedInputStream(std::istream& in_stream) {
   3264     std::vector<std::string> output;
   3265     while (in_stream.good()) {
   3266       std::string dot;
   3267       std::getline(in_stream, dot);
   3268       if (android::base::StartsWith(dot, "#") || dot.empty()) {
   3269         continue;
   3270       }
   3271       output.push_back(dot);
   3272     }
   3273     return output;
   3274   }
   3275 
   3276   // Read lines from the given file, dropping comments and empty lines.
   3277   static std::vector<std::string> ReadCommentedInputFromFile(const std::string& input_filename) {
   3278     std::unique_ptr<std::ifstream> input_file(new std::ifstream(input_filename, std::ifstream::in));
   3279     if (input_file.get() == nullptr) {
   3280       LOG(ERROR) << "Failed to open input file " << input_filename;
   3281       return std::vector<std::string>();
   3282     }
   3283     std::vector<std::string> result = ReadCommentedInputStream(*input_file);
   3284     input_file->close();
   3285     return result;
   3286   }
   3287 
   3288   // Prepare a class, i.e., ensure it has a filled IMT. Will do so recursively for superclasses,
   3289   // and note in the given set that the work was done.
   3290   static void PrepareClass(Runtime* runtime,
   3291                            Handle<mirror::Class> h_klass,
   3292                            std::unordered_set<std::string>* done)
   3293       REQUIRES_SHARED(Locks::mutator_lock_) {
   3294     if (!h_klass->ShouldHaveImt()) {
   3295       return;
   3296     }
   3297 
   3298     std::string name;
   3299     name = h_klass->GetDescriptor(&name);
   3300 
   3301     if (done->find(name) != done->end()) {
   3302       return;
   3303     }
   3304     done->insert(name);
   3305 
   3306     if (h_klass->HasSuperClass()) {
   3307       StackHandleScope<1> h(Thread::Current());
   3308       PrepareClass(runtime, h.NewHandle<mirror::Class>(h_klass->GetSuperClass()), done);
   3309     }
   3310 
   3311     if (!h_klass->IsTemp()) {
   3312       runtime->GetClassLinker()->FillIMTAndConflictTables(h_klass.Get());
   3313     }
   3314   }
   3315 };
   3316 
   3317 struct OatdumpArgs : public CmdlineArgs {
   3318  protected:
   3319   using Base = CmdlineArgs;
   3320 
   3321   virtual ParseStatus ParseCustom(const StringPiece& option,
   3322                                   std::string* error_msg) OVERRIDE {
   3323     {
   3324       ParseStatus base_parse = Base::ParseCustom(option, error_msg);
   3325       if (base_parse != kParseUnknownArgument) {
   3326         return base_parse;
   3327       }
   3328     }
   3329 
   3330     if (option.starts_with("--oat-file=")) {
   3331       oat_filename_ = option.substr(strlen("--oat-file=")).data();
   3332     } else if (option.starts_with("--image=")) {
   3333       image_location_ = option.substr(strlen("--image=")).data();
   3334     } else if (option == "--no-dump:vmap") {
   3335       dump_vmap_ = false;
   3336     } else if (option =="--dump:code_info_stack_maps") {
   3337       dump_code_info_stack_maps_ = true;
   3338     } else if (option == "--no-disassemble") {
   3339       disassemble_code_ = false;
   3340     } else if (option =="--header-only") {
   3341       dump_header_only_ = true;
   3342     } else if (option.starts_with("--symbolize=")) {
   3343       oat_filename_ = option.substr(strlen("--symbolize=")).data();
   3344       symbolize_ = true;
   3345     } else if (option.starts_with("--only-keep-debug")) {
   3346       only_keep_debug_ = true;
   3347     } else if (option.starts_with("--class-filter=")) {
   3348       class_filter_ = option.substr(strlen("--class-filter=")).data();
   3349     } else if (option.starts_with("--method-filter=")) {
   3350       method_filter_ = option.substr(strlen("--method-filter=")).data();
   3351     } else if (option.starts_with("--list-classes")) {
   3352       list_classes_ = true;
   3353     } else if (option.starts_with("--list-methods")) {
   3354       list_methods_ = true;
   3355     } else if (option.starts_with("--export-dex-to=")) {
   3356       export_dex_location_ = option.substr(strlen("--export-dex-to=")).data();
   3357     } else if (option.starts_with("--addr2instr=")) {
   3358       if (!ParseUint(option.substr(strlen("--addr2instr=")).data(), &addr2instr_)) {
   3359         *error_msg = "Address conversion failed";
   3360         return kParseError;
   3361       }
   3362     } else if (option.starts_with("--app-image=")) {
   3363       app_image_ = option.substr(strlen("--app-image=")).data();
   3364     } else if (option.starts_with("--app-oat=")) {
   3365       app_oat_ = option.substr(strlen("--app-oat=")).data();
   3366     } else if (option.starts_with("--dump-imt=")) {
   3367       imt_dump_ = option.substr(strlen("--dump-imt=")).data();
   3368     } else if (option == "--dump-imt-stats") {
   3369       imt_stat_dump_ = true;
   3370     } else {
   3371       return kParseUnknownArgument;
   3372     }
   3373 
   3374     return kParseOk;
   3375   }
   3376 
   3377   virtual ParseStatus ParseChecks(std::string* error_msg) OVERRIDE {
   3378     // Infer boot image location from the image location if possible.
   3379     if (boot_image_location_ == nullptr) {
   3380       boot_image_location_ = image_location_;
   3381     }
   3382 
   3383     // Perform the parent checks.
   3384     ParseStatus parent_checks = Base::ParseChecks(error_msg);
   3385     if (parent_checks != kParseOk) {
   3386       return parent_checks;
   3387     }
   3388 
   3389     // Perform our own checks.
   3390     if (image_location_ == nullptr && oat_filename_ == nullptr) {
   3391       *error_msg = "Either --image or --oat-file must be specified";
   3392       return kParseError;
   3393     } else if (image_location_ != nullptr && oat_filename_ != nullptr) {
   3394       *error_msg = "Either --image or --oat-file must be specified but not both";
   3395       return kParseError;
   3396     }
   3397 
   3398     return kParseOk;
   3399   }
   3400 
   3401   virtual std::string GetUsage() const {
   3402     std::string usage;
   3403 
   3404     usage +=
   3405         "Usage: oatdump [options] ...\n"
   3406         "    Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art\n"
   3407         "    Example: adb shell oatdump --image=/system/framework/boot.art\n"
   3408         "\n"
   3409         // Either oat-file or image is required.
   3410         "  --oat-file=<file.oat>: specifies an input oat filename.\n"
   3411         "      Example: --oat-file=/system/framework/boot.oat\n"
   3412         "\n"
   3413         "  --image=<file.art>: specifies an input image location.\n"
   3414         "      Example: --image=/system/framework/boot.art\n"
   3415         "\n"
   3416         "  --app-image=<file.art>: specifies an input app image. Must also have a specified\n"
   3417         " boot image and app oat file.\n"
   3418         "      Example: --app-image=app.art\n"
   3419         "\n"
   3420         "  --app-oat=<file.odex>: specifies an input app oat.\n"
   3421         "      Example: --app-oat=app.odex\n"
   3422         "\n";
   3423 
   3424     usage += Base::GetUsage();
   3425 
   3426     usage +=  // Optional.
   3427         "  --no-dump:vmap may be used to disable vmap dumping.\n"
   3428         "      Example: --no-dump:vmap\n"
   3429         "\n"
   3430         "  --dump:code_info_stack_maps enables dumping of stack maps in CodeInfo sections.\n"
   3431         "      Example: --dump:code_info_stack_maps\n"
   3432         "\n"
   3433         "  --no-disassemble may be used to disable disassembly.\n"
   3434         "      Example: --no-disassemble\n"
   3435         "\n"
   3436         "  --header-only may be used to print only the oat header.\n"
   3437         "      Example: --header-only\n"
   3438         "\n"
   3439         "  --list-classes may be used to list target file classes (can be used with filters).\n"
   3440         "      Example: --list-classes\n"
   3441         "      Example: --list-classes --class-filter=com.example.foo\n"
   3442         "\n"
   3443         "  --list-methods may be used to list target file methods (can be used with filters).\n"
   3444         "      Example: --list-methods\n"
   3445         "      Example: --list-methods --class-filter=com.example --method-filter=foo\n"
   3446         "\n"
   3447         "  --symbolize=<file.oat>: output a copy of file.oat with elf symbols included.\n"
   3448         "      Example: --symbolize=/system/framework/boot.oat\n"
   3449         "\n"
   3450         "  --only-keep-debug<file.oat>: Modifies the behaviour of --symbolize so that\n"
   3451         "      .rodata and .text sections are omitted in the output file to save space.\n"
   3452         "      Example: --symbolize=/system/framework/boot.oat --only-keep-debug\n"
   3453         "\n"
   3454         "  --class-filter=<class name>: only dumps classes that contain the filter.\n"
   3455         "      Example: --class-filter=com.example.foo\n"
   3456         "\n"
   3457         "  --method-filter=<method name>: only dumps methods that contain the filter.\n"
   3458         "      Example: --method-filter=foo\n"
   3459         "\n"
   3460         "  --export-dex-to=<directory>: may be used to export oat embedded dex files.\n"
   3461         "      Example: --export-dex-to=/data/local/tmp\n"
   3462         "\n"
   3463         "  --addr2instr=<address>: output matching method disassembled code from relative\n"
   3464         "                          address (e.g. PC from crash dump)\n"
   3465         "      Example: --addr2instr=0x00001a3b\n"
   3466         "\n"
   3467         "  --dump-imt=<file.txt>: output IMT collisions (if any) for the given receiver\n"
   3468         "                         types and interface methods in the given file. The file\n"
   3469         "                         is read line-wise, where each line should either be a class\n"
   3470         "                         name or descriptor, or a class name/descriptor and a prefix\n"
   3471         "                         of a complete method name (separated by a whitespace).\n"
   3472         "      Example: --dump-imt=imt.txt\n"
   3473         "\n"
   3474         "  --dump-imt-stats: output IMT statistics for the given boot image\n"
   3475         "      Example: --dump-imt-stats"
   3476         "\n";
   3477 
   3478     return usage;
   3479   }
   3480 
   3481  public:
   3482   const char* oat_filename_ = nullptr;
   3483   const char* class_filter_ = "";
   3484   const char* method_filter_ = "";
   3485   const char* image_location_ = nullptr;
   3486   std::string elf_filename_prefix_;
   3487   std::string imt_dump_;
   3488   bool dump_vmap_ = true;
   3489   bool dump_code_info_stack_maps_ = false;
   3490   bool disassemble_code_ = true;
   3491   bool symbolize_ = false;
   3492   bool only_keep_debug_ = false;
   3493   bool list_classes_ = false;
   3494   bool list_methods_ = false;
   3495   bool dump_header_only_ = false;
   3496   bool imt_stat_dump_ = false;
   3497   uint32_t addr2instr_ = 0;
   3498   const char* export_dex_location_ = nullptr;
   3499   const char* app_image_ = nullptr;
   3500   const char* app_oat_ = nullptr;
   3501 };
   3502 
   3503 struct OatdumpMain : public CmdlineMain<OatdumpArgs> {
   3504   virtual bool NeedsRuntime() OVERRIDE {
   3505     CHECK(args_ != nullptr);
   3506 
   3507     // If we are only doing the oat file, disable absolute_addresses. Keep them for image dumping.
   3508     bool absolute_addresses = (args_->oat_filename_ == nullptr);
   3509 
   3510     oat_dumper_options_.reset(new OatDumperOptions(
   3511         args_->dump_vmap_,
   3512         args_->dump_code_info_stack_maps_,
   3513         args_->disassemble_code_,
   3514         absolute_addresses,
   3515         args_->class_filter_,
   3516         args_->method_filter_,
   3517         args_->list_classes_,
   3518         args_->list_methods_,
   3519         args_->dump_header_only_,
   3520         args_->export_dex_location_,
   3521         args_->app_image_,
   3522         args_->app_oat_,
   3523         args_->addr2instr_));
   3524 
   3525     return (args_->boot_image_location_ != nullptr ||
   3526             args_->image_location_ != nullptr ||
   3527             !args_->imt_dump_.empty()) &&
   3528           !args_->symbolize_;
   3529   }
   3530 
   3531   virtual bool ExecuteWithoutRuntime() OVERRIDE {
   3532     CHECK(args_ != nullptr);
   3533     CHECK(args_->oat_filename_ != nullptr);
   3534 
   3535     MemMap::Init();
   3536 
   3537     if (args_->symbolize_) {
   3538       // ELF has special kind of section called SHT_NOBITS which allows us to create
   3539       // sections which exist but their data is omitted from the ELF file to save space.
   3540       // This is what "strip --only-keep-debug" does when it creates separate ELF file
   3541       // with only debug data. We use it in similar way to exclude .rodata and .text.
   3542       bool no_bits = args_->only_keep_debug_;
   3543       return SymbolizeOat(args_->oat_filename_, args_->output_name_, no_bits) == EXIT_SUCCESS;
   3544     } else {
   3545       return DumpOat(nullptr,
   3546                      args_->oat_filename_,
   3547                      oat_dumper_options_.get(),
   3548                      args_->os_) == EXIT_SUCCESS;
   3549     }
   3550   }
   3551 
   3552   virtual bool ExecuteWithRuntime(Runtime* runtime) {
   3553     CHECK(args_ != nullptr);
   3554 
   3555     if (!args_->imt_dump_.empty() || args_->imt_stat_dump_) {
   3556       return IMTDumper::Dump(runtime,
   3557                              args_->imt_dump_,
   3558                              args_->imt_stat_dump_,
   3559                              args_->oat_filename_);
   3560     }
   3561 
   3562     if (args_->oat_filename_ != nullptr) {
   3563       return DumpOat(runtime,
   3564                      args_->oat_filename_,
   3565                      oat_dumper_options_.get(),
   3566                      args_->os_) == EXIT_SUCCESS;
   3567     }
   3568 
   3569     return DumpImages(runtime, oat_dumper_options_.get(), args_->os_) == EXIT_SUCCESS;
   3570   }
   3571 
   3572   std::unique_ptr<OatDumperOptions> oat_dumper_options_;
   3573 };
   3574 
   3575 }  // namespace art
   3576 
   3577 int main(int argc, char** argv) {
   3578   art::OatdumpMain main;
   3579   return main.Main(argc, argv);
   3580 }
   3581