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 <vector>
     27 
     28 #include "arch/instruction_set_features.h"
     29 #include "art_field-inl.h"
     30 #include "art_method-inl.h"
     31 #include "base/stl_util.h"
     32 #include "base/unix_file/fd_file.h"
     33 #include "class_linker.h"
     34 #include "class_linker-inl.h"
     35 #include "debug/elf_debug_writer.h"
     36 #include "debug/method_debug_info.h"
     37 #include "dex_file-inl.h"
     38 #include "dex_instruction.h"
     39 #include "disassembler.h"
     40 #include "elf_builder.h"
     41 #include "gc/space/image_space.h"
     42 #include "gc/space/large_object_space.h"
     43 #include "gc/space/space-inl.h"
     44 #include "image-inl.h"
     45 #include "indenter.h"
     46 #include "linker/buffered_output_stream.h"
     47 #include "linker/file_output_stream.h"
     48 #include "mirror/array-inl.h"
     49 #include "mirror/class-inl.h"
     50 #include "mirror/dex_cache-inl.h"
     51 #include "mirror/object-inl.h"
     52 #include "mirror/object_array-inl.h"
     53 #include "oat.h"
     54 #include "oat_file-inl.h"
     55 #include "oat_file_manager.h"
     56 #include "os.h"
     57 #include "safe_map.h"
     58 #include "scoped_thread_state_change.h"
     59 #include "stack_map.h"
     60 #include "ScopedLocalRef.h"
     61 #include "thread_list.h"
     62 #include "type_lookup_table.h"
     63 #include "verifier/method_verifier.h"
     64 #include "well_known_classes.h"
     65 
     66 #include <sys/stat.h>
     67 #include "cmdline.h"
     68 
     69 namespace art {
     70 
     71 const char* image_methods_descriptions_[] = {
     72   "kResolutionMethod",
     73   "kImtConflictMethod",
     74   "kImtUnimplementedMethod",
     75   "kCalleeSaveMethod",
     76   "kRefsOnlySaveMethod",
     77   "kRefsAndArgsSaveMethod",
     78 };
     79 
     80 const char* image_roots_descriptions_[] = {
     81   "kDexCaches",
     82   "kClassRoots",
     83 };
     84 
     85 // Map is so that we don't allocate multiple dex files for the same OatDexFile.
     86 static std::map<const OatFile::OatDexFile*,
     87                 std::unique_ptr<const DexFile>> opened_dex_files;
     88 
     89 const DexFile* OpenDexFile(const OatFile::OatDexFile* oat_dex_file, std::string* error_msg) {
     90   DCHECK(oat_dex_file != nullptr);
     91   auto it = opened_dex_files.find(oat_dex_file);
     92   if (it != opened_dex_files.end()) {
     93     return it->second.get();
     94   }
     95   const DexFile* ret = oat_dex_file->OpenDexFile(error_msg).release();
     96   opened_dex_files.emplace(oat_dex_file, std::unique_ptr<const DexFile>(ret));
     97   return ret;
     98 }
     99 
    100 template <typename ElfTypes>
    101 class OatSymbolizer FINAL {
    102  public:
    103   OatSymbolizer(const OatFile* oat_file, const std::string& output_name, bool no_bits) :
    104       oat_file_(oat_file),
    105       builder_(nullptr),
    106       output_name_(output_name.empty() ? "symbolized.oat" : output_name),
    107       no_bits_(no_bits) {
    108   }
    109 
    110   bool Symbolize() {
    111     const InstructionSet isa = oat_file_->GetOatHeader().GetInstructionSet();
    112     const InstructionSetFeatures* features = InstructionSetFeatures::FromBitmap(
    113         isa, oat_file_->GetOatHeader().GetInstructionSetFeaturesBitmap());
    114 
    115     File* elf_file = OS::CreateEmptyFile(output_name_.c_str());
    116     std::unique_ptr<BufferedOutputStream> output_stream(
    117         MakeUnique<BufferedOutputStream>(MakeUnique<FileOutputStream>(elf_file)));
    118     builder_.reset(new ElfBuilder<ElfTypes>(isa, features, output_stream.get()));
    119 
    120     builder_->Start();
    121 
    122     auto* rodata = builder_->GetRoData();
    123     auto* text = builder_->GetText();
    124     auto* bss = builder_->GetBss();
    125 
    126     const uint8_t* rodata_begin = oat_file_->Begin();
    127     const size_t rodata_size = oat_file_->GetOatHeader().GetExecutableOffset();
    128     if (no_bits_) {
    129       rodata->WriteNoBitsSection(rodata_size);
    130     } else {
    131       rodata->Start();
    132       rodata->WriteFully(rodata_begin, rodata_size);
    133       rodata->End();
    134     }
    135 
    136     const uint8_t* text_begin = oat_file_->Begin() + rodata_size;
    137     const size_t text_size = oat_file_->End() - text_begin;
    138     if (no_bits_) {
    139       text->WriteNoBitsSection(text_size);
    140     } else {
    141       text->Start();
    142       text->WriteFully(text_begin, text_size);
    143       text->End();
    144     }
    145 
    146     if (oat_file_->BssSize() != 0) {
    147       bss->WriteNoBitsSection(oat_file_->BssSize());
    148     }
    149 
    150     if (isa == kMips || isa == kMips64) {
    151       builder_->WriteMIPSabiflagsSection();
    152     }
    153     builder_->PrepareDynamicSection(
    154         elf_file->GetPath(), rodata_size, text_size, oat_file_->BssSize());
    155     builder_->WriteDynamicSection();
    156 
    157     Walk();
    158     for (const auto& trampoline : debug::MakeTrampolineInfos(oat_file_->GetOatHeader())) {
    159       method_debug_infos_.push_back(trampoline);
    160     }
    161 
    162     debug::WriteDebugInfo(builder_.get(),
    163                           ArrayRef<const debug::MethodDebugInfo>(method_debug_infos_),
    164                           dwarf::DW_DEBUG_FRAME_FORMAT,
    165                           true /* write_oat_patches */);
    166 
    167     builder_->End();
    168 
    169     return builder_->Good();
    170   }
    171 
    172   void Walk() {
    173     std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file_->GetOatDexFiles();
    174     for (size_t i = 0; i < oat_dex_files.size(); i++) {
    175       const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
    176       CHECK(oat_dex_file != nullptr);
    177       WalkOatDexFile(oat_dex_file);
    178     }
    179   }
    180 
    181   void WalkOatDexFile(const OatFile::OatDexFile* oat_dex_file) {
    182     std::string error_msg;
    183     const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
    184     if (dex_file == nullptr) {
    185       return;
    186     }
    187     for (size_t class_def_index = 0;
    188         class_def_index < dex_file->NumClassDefs();
    189         class_def_index++) {
    190       const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
    191       OatClassType type = oat_class.GetType();
    192       switch (type) {
    193         case kOatClassAllCompiled:
    194         case kOatClassSomeCompiled:
    195           WalkOatClass(oat_class, *dex_file, class_def_index);
    196           break;
    197 
    198         case kOatClassNoneCompiled:
    199         case kOatClassMax:
    200           // Ignore.
    201           break;
    202       }
    203     }
    204   }
    205 
    206   void WalkOatClass(const OatFile::OatClass& oat_class,
    207                     const DexFile& dex_file,
    208                     uint32_t class_def_index) {
    209     const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
    210     const uint8_t* class_data = dex_file.GetClassData(class_def);
    211     if (class_data == nullptr) {  // empty class such as a marker interface?
    212       return;
    213     }
    214     // Note: even if this is an interface or a native class, we still have to walk it, as there
    215     //       might be a static initializer.
    216     ClassDataItemIterator it(dex_file, class_data);
    217     uint32_t class_method_idx = 0;
    218     for (; it.HasNextStaticField(); it.Next()) { /* skip */ }
    219     for (; it.HasNextInstanceField(); it.Next()) { /* skip */ }
    220     for (; it.HasNextDirectMethod() || it.HasNextVirtualMethod(); it.Next()) {
    221       WalkOatMethod(oat_class.GetOatMethod(class_method_idx++),
    222                     dex_file,
    223                     class_def_index,
    224                     it.GetMemberIndex(),
    225                     it.GetMethodCodeItem(),
    226                     it.GetMethodAccessFlags());
    227     }
    228     DCHECK(!it.HasNext());
    229   }
    230 
    231   void WalkOatMethod(const OatFile::OatMethod& oat_method,
    232                      const DexFile& dex_file,
    233                      uint32_t class_def_index,
    234                      uint32_t dex_method_index,
    235                      const DexFile::CodeItem* code_item,
    236                      uint32_t method_access_flags) {
    237     if ((method_access_flags & kAccAbstract) != 0) {
    238       // Abstract method, no code.
    239       return;
    240     }
    241     const OatHeader& oat_header = oat_file_->GetOatHeader();
    242     const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
    243     if (method_header == nullptr || method_header->GetCodeSize() == 0) {
    244       // No code.
    245       return;
    246     }
    247 
    248     uint32_t entry_point = oat_method.GetCodeOffset() - oat_header.GetExecutableOffset();
    249     // Clear Thumb2 bit.
    250     const void* code_address = EntryPointToCodePointer(reinterpret_cast<void*>(entry_point));
    251 
    252     debug::MethodDebugInfo info = debug::MethodDebugInfo();
    253     info.trampoline_name = nullptr;
    254     info.dex_file = &dex_file;
    255     info.class_def_index = class_def_index;
    256     info.dex_method_index = dex_method_index;
    257     info.access_flags = method_access_flags;
    258     info.code_item = code_item;
    259     info.isa = oat_header.GetInstructionSet();
    260     info.deduped = !seen_offsets_.insert(oat_method.GetCodeOffset()).second;
    261     info.is_native_debuggable = oat_header.IsNativeDebuggable();
    262     info.is_optimized = method_header->IsOptimized();
    263     info.is_code_address_text_relative = true;
    264     info.code_address = reinterpret_cast<uintptr_t>(code_address);
    265     info.code_size = method_header->GetCodeSize();
    266     info.frame_size_in_bytes = method_header->GetFrameSizeInBytes();
    267     info.code_info = info.is_optimized ? method_header->GetOptimizedCodeInfoPtr() : nullptr;
    268     info.cfi = ArrayRef<uint8_t>();
    269     method_debug_infos_.push_back(info);
    270   }
    271 
    272  private:
    273   const OatFile* oat_file_;
    274   std::unique_ptr<ElfBuilder<ElfTypes> > builder_;
    275   std::vector<debug::MethodDebugInfo> method_debug_infos_;
    276   std::unordered_set<uint32_t> seen_offsets_;
    277   const std::string output_name_;
    278   bool no_bits_;
    279 };
    280 
    281 class OatDumperOptions {
    282  public:
    283   OatDumperOptions(bool dump_vmap,
    284                    bool dump_code_info_stack_maps,
    285                    bool disassemble_code,
    286                    bool absolute_addresses,
    287                    const char* class_filter,
    288                    const char* method_filter,
    289                    bool list_classes,
    290                    bool list_methods,
    291                    bool dump_header_only,
    292                    const char* export_dex_location,
    293                    const char* app_image,
    294                    const char* app_oat,
    295                    uint32_t addr2instr)
    296     : dump_vmap_(dump_vmap),
    297       dump_code_info_stack_maps_(dump_code_info_stack_maps),
    298       disassemble_code_(disassemble_code),
    299       absolute_addresses_(absolute_addresses),
    300       class_filter_(class_filter),
    301       method_filter_(method_filter),
    302       list_classes_(list_classes),
    303       list_methods_(list_methods),
    304       dump_header_only_(dump_header_only),
    305       export_dex_location_(export_dex_location),
    306       app_image_(app_image),
    307       app_oat_(app_oat),
    308       addr2instr_(addr2instr),
    309       class_loader_(nullptr) {}
    310 
    311   const bool dump_vmap_;
    312   const bool dump_code_info_stack_maps_;
    313   const bool disassemble_code_;
    314   const bool absolute_addresses_;
    315   const char* const class_filter_;
    316   const char* const method_filter_;
    317   const bool list_classes_;
    318   const bool list_methods_;
    319   const bool dump_header_only_;
    320   const char* const export_dex_location_;
    321   const char* const app_image_;
    322   const char* const app_oat_;
    323   uint32_t addr2instr_;
    324   Handle<mirror::ClassLoader>* class_loader_;
    325 };
    326 
    327 class OatDumper {
    328  public:
    329   OatDumper(const OatFile& oat_file, const OatDumperOptions& options)
    330     : oat_file_(oat_file),
    331       oat_dex_files_(oat_file.GetOatDexFiles()),
    332       options_(options),
    333       resolved_addr2instr_(0),
    334       instruction_set_(oat_file_.GetOatHeader().GetInstructionSet()),
    335       disassembler_(Disassembler::Create(instruction_set_,
    336                                          new DisassemblerOptions(options_.absolute_addresses_,
    337                                                                  oat_file.Begin(),
    338                                                                  oat_file.End(),
    339                                                                  true /* can_read_literals_ */))) {
    340     CHECK(options_.class_loader_ != nullptr);
    341     CHECK(options_.class_filter_ != nullptr);
    342     CHECK(options_.method_filter_ != nullptr);
    343     AddAllOffsets();
    344   }
    345 
    346   ~OatDumper() {
    347     delete disassembler_;
    348   }
    349 
    350   InstructionSet GetInstructionSet() {
    351     return instruction_set_;
    352   }
    353 
    354   bool Dump(std::ostream& os) {
    355     bool success = true;
    356     const OatHeader& oat_header = oat_file_.GetOatHeader();
    357 
    358     os << "MAGIC:\n";
    359     os << oat_header.GetMagic() << "\n\n";
    360 
    361     os << "LOCATION:\n";
    362     os << oat_file_.GetLocation() << "\n\n";
    363 
    364     os << "CHECKSUM:\n";
    365     os << StringPrintf("0x%08x\n\n", oat_header.GetChecksum());
    366 
    367     os << "INSTRUCTION SET:\n";
    368     os << oat_header.GetInstructionSet() << "\n\n";
    369 
    370     {
    371       std::unique_ptr<const InstructionSetFeatures> features(
    372           InstructionSetFeatures::FromBitmap(oat_header.GetInstructionSet(),
    373                                              oat_header.GetInstructionSetFeaturesBitmap()));
    374       os << "INSTRUCTION SET FEATURES:\n";
    375       os << features->GetFeatureString() << "\n\n";
    376     }
    377 
    378     os << "DEX FILE COUNT:\n";
    379     os << oat_header.GetDexFileCount() << "\n\n";
    380 
    381 #define DUMP_OAT_HEADER_OFFSET(label, offset) \
    382     os << label " OFFSET:\n"; \
    383     os << StringPrintf("0x%08x", oat_header.offset()); \
    384     if (oat_header.offset() != 0 && options_.absolute_addresses_) { \
    385       os << StringPrintf(" (%p)", oat_file_.Begin() + oat_header.offset()); \
    386     } \
    387     os << StringPrintf("\n\n");
    388 
    389     DUMP_OAT_HEADER_OFFSET("EXECUTABLE", GetExecutableOffset);
    390     DUMP_OAT_HEADER_OFFSET("INTERPRETER TO INTERPRETER BRIDGE",
    391                            GetInterpreterToInterpreterBridgeOffset);
    392     DUMP_OAT_HEADER_OFFSET("INTERPRETER TO COMPILED CODE BRIDGE",
    393                            GetInterpreterToCompiledCodeBridgeOffset);
    394     DUMP_OAT_HEADER_OFFSET("JNI DLSYM LOOKUP",
    395                            GetJniDlsymLookupOffset);
    396     DUMP_OAT_HEADER_OFFSET("QUICK GENERIC JNI TRAMPOLINE",
    397                            GetQuickGenericJniTrampolineOffset);
    398     DUMP_OAT_HEADER_OFFSET("QUICK IMT CONFLICT TRAMPOLINE",
    399                            GetQuickImtConflictTrampolineOffset);
    400     DUMP_OAT_HEADER_OFFSET("QUICK RESOLUTION TRAMPOLINE",
    401                            GetQuickResolutionTrampolineOffset);
    402     DUMP_OAT_HEADER_OFFSET("QUICK TO INTERPRETER BRIDGE",
    403                            GetQuickToInterpreterBridgeOffset);
    404 #undef DUMP_OAT_HEADER_OFFSET
    405 
    406     os << "IMAGE PATCH DELTA:\n";
    407     os << StringPrintf("%d (0x%08x)\n\n",
    408                        oat_header.GetImagePatchDelta(),
    409                        oat_header.GetImagePatchDelta());
    410 
    411     os << "IMAGE FILE LOCATION OAT CHECKSUM:\n";
    412     os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatChecksum());
    413 
    414     os << "IMAGE FILE LOCATION OAT BEGIN:\n";
    415     os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatDataBegin());
    416 
    417     // Print the key-value store.
    418     {
    419       os << "KEY VALUE STORE:\n";
    420       size_t index = 0;
    421       const char* key;
    422       const char* value;
    423       while (oat_header.GetStoreKeyValuePairByIndex(index, &key, &value)) {
    424         os << key << " = " << value << "\n";
    425         index++;
    426       }
    427       os << "\n";
    428     }
    429 
    430     if (options_.absolute_addresses_) {
    431       os << "BEGIN:\n";
    432       os << reinterpret_cast<const void*>(oat_file_.Begin()) << "\n\n";
    433 
    434       os << "END:\n";
    435       os << reinterpret_cast<const void*>(oat_file_.End()) << "\n\n";
    436     }
    437 
    438     os << "SIZE:\n";
    439     os << oat_file_.Size() << "\n\n";
    440 
    441     os << std::flush;
    442 
    443     // If set, adjust relative address to be searched
    444     if (options_.addr2instr_ != 0) {
    445       resolved_addr2instr_ = options_.addr2instr_ + oat_header.GetExecutableOffset();
    446       os << "SEARCH ADDRESS (executable offset + input):\n";
    447       os << StringPrintf("0x%08x\n\n", resolved_addr2instr_);
    448     }
    449 
    450     if (!options_.dump_header_only_) {
    451       for (size_t i = 0; i < oat_dex_files_.size(); i++) {
    452         const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
    453         CHECK(oat_dex_file != nullptr);
    454 
    455         // If file export selected skip file analysis
    456         if (options_.export_dex_location_) {
    457           if (!ExportDexFile(os, *oat_dex_file)) {
    458             success = false;
    459           }
    460         } else {
    461           if (!DumpOatDexFile(os, *oat_dex_file)) {
    462             success = false;
    463           }
    464         }
    465       }
    466     }
    467 
    468     os << std::flush;
    469     return success;
    470   }
    471 
    472   size_t ComputeSize(const void* oat_data) {
    473     if (reinterpret_cast<const uint8_t*>(oat_data) < oat_file_.Begin() ||
    474         reinterpret_cast<const uint8_t*>(oat_data) > oat_file_.End()) {
    475       return 0;  // Address not in oat file
    476     }
    477     uintptr_t begin_offset = reinterpret_cast<uintptr_t>(oat_data) -
    478                              reinterpret_cast<uintptr_t>(oat_file_.Begin());
    479     auto it = offsets_.upper_bound(begin_offset);
    480     CHECK(it != offsets_.end());
    481     uintptr_t end_offset = *it;
    482     return end_offset - begin_offset;
    483   }
    484 
    485   InstructionSet GetOatInstructionSet() {
    486     return oat_file_.GetOatHeader().GetInstructionSet();
    487   }
    488 
    489   const void* GetQuickOatCode(ArtMethod* m) SHARED_REQUIRES(Locks::mutator_lock_) {
    490     for (size_t i = 0; i < oat_dex_files_.size(); i++) {
    491       const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
    492       CHECK(oat_dex_file != nullptr);
    493       std::string error_msg;
    494       const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
    495       if (dex_file == nullptr) {
    496         LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation()
    497             << "': " << error_msg;
    498       } else {
    499         const char* descriptor = m->GetDeclaringClassDescriptor();
    500         const DexFile::ClassDef* class_def =
    501             dex_file->FindClassDef(descriptor, ComputeModifiedUtf8Hash(descriptor));
    502         if (class_def != nullptr) {
    503           uint16_t class_def_index = dex_file->GetIndexForClassDef(*class_def);
    504           const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
    505           size_t method_index = m->GetMethodIndex();
    506           return oat_class.GetOatMethod(method_index).GetQuickCode();
    507         }
    508       }
    509     }
    510     return nullptr;
    511   }
    512 
    513  private:
    514   void AddAllOffsets() {
    515     // We don't know the length of the code for each method, but we need to know where to stop
    516     // when disassembling. What we do know is that a region of code will be followed by some other
    517     // region, so if we keep a sorted sequence of the start of each region, we can infer the length
    518     // of a piece of code by using upper_bound to find the start of the next region.
    519     for (size_t i = 0; i < oat_dex_files_.size(); i++) {
    520       const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
    521       CHECK(oat_dex_file != nullptr);
    522       std::string error_msg;
    523       const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
    524       if (dex_file == nullptr) {
    525         LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation()
    526             << "': " << error_msg;
    527         continue;
    528       }
    529       offsets_.insert(reinterpret_cast<uintptr_t>(&dex_file->GetHeader()));
    530       for (size_t class_def_index = 0;
    531            class_def_index < dex_file->NumClassDefs();
    532            class_def_index++) {
    533         const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
    534         const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
    535         const uint8_t* class_data = dex_file->GetClassData(class_def);
    536         if (class_data != nullptr) {
    537           ClassDataItemIterator it(*dex_file, class_data);
    538           SkipAllFields(it);
    539           uint32_t class_method_index = 0;
    540           while (it.HasNextDirectMethod()) {
    541             AddOffsets(oat_class.GetOatMethod(class_method_index++));
    542             it.Next();
    543           }
    544           while (it.HasNextVirtualMethod()) {
    545             AddOffsets(oat_class.GetOatMethod(class_method_index++));
    546             it.Next();
    547           }
    548         }
    549       }
    550     }
    551 
    552     // If the last thing in the file is code for a method, there won't be an offset for the "next"
    553     // thing. Instead of having a special case in the upper_bound code, let's just add an entry
    554     // for the end of the file.
    555     offsets_.insert(oat_file_.Size());
    556   }
    557 
    558   static uint32_t AlignCodeOffset(uint32_t maybe_thumb_offset) {
    559     return maybe_thumb_offset & ~0x1;  // TODO: Make this Thumb2 specific.
    560   }
    561 
    562   void AddOffsets(const OatFile::OatMethod& oat_method) {
    563     uint32_t code_offset = oat_method.GetCodeOffset();
    564     if (oat_file_.GetOatHeader().GetInstructionSet() == kThumb2) {
    565       code_offset &= ~0x1;
    566     }
    567     offsets_.insert(code_offset);
    568     offsets_.insert(oat_method.GetVmapTableOffset());
    569   }
    570 
    571   bool DumpOatDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) {
    572     bool success = true;
    573     bool stop_analysis = false;
    574     os << "OatDexFile:\n";
    575     os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str());
    576     os << StringPrintf("checksum: 0x%08x\n", oat_dex_file.GetDexFileLocationChecksum());
    577 
    578     // Print embedded dex file data range.
    579     const uint8_t* const oat_file_begin = oat_dex_file.GetOatFile()->Begin();
    580     const uint8_t* const dex_file_pointer = oat_dex_file.GetDexFilePointer();
    581     uint32_t dex_offset = dchecked_integral_cast<uint32_t>(dex_file_pointer - oat_file_begin);
    582     os << StringPrintf("dex-file: 0x%08x..0x%08x\n",
    583                        dex_offset,
    584                        dchecked_integral_cast<uint32_t>(dex_offset + oat_dex_file.FileSize() - 1));
    585 
    586     // Create the dex file early. A lot of print-out things depend on it.
    587     std::string error_msg;
    588     const DexFile* const dex_file = OpenDexFile(&oat_dex_file, &error_msg);
    589     if (dex_file == nullptr) {
    590       os << "NOT FOUND: " << error_msg << "\n\n";
    591       os << std::flush;
    592       return false;
    593     }
    594 
    595     // Print lookup table, if it exists.
    596     if (oat_dex_file.GetLookupTableData() != nullptr) {
    597       uint32_t table_offset = dchecked_integral_cast<uint32_t>(
    598           oat_dex_file.GetLookupTableData() - oat_file_begin);
    599       uint32_t table_size = TypeLookupTable::RawDataLength(*dex_file);
    600       os << StringPrintf("type-table: 0x%08x..0x%08x\n",
    601                          table_offset,
    602                          table_offset + table_size - 1);
    603     }
    604 
    605     VariableIndentationOutputStream vios(&os);
    606     ScopedIndentation indent1(&vios);
    607     for (size_t class_def_index = 0;
    608          class_def_index < dex_file->NumClassDefs();
    609          class_def_index++) {
    610       const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
    611       const char* descriptor = dex_file->GetClassDescriptor(class_def);
    612 
    613       // TODO: Support regex
    614       if (DescriptorToDot(descriptor).find(options_.class_filter_) == std::string::npos) {
    615         continue;
    616       }
    617 
    618       uint32_t oat_class_offset = oat_dex_file.GetOatClassOffset(class_def_index);
    619       const OatFile::OatClass oat_class = oat_dex_file.GetOatClass(class_def_index);
    620       os << StringPrintf("%zd: %s (offset=0x%08x) (type_idx=%d)",
    621                          class_def_index, descriptor, oat_class_offset, class_def.class_idx_)
    622          << " (" << oat_class.GetStatus() << ")"
    623          << " (" << oat_class.GetType() << ")\n";
    624       // TODO: include bitmap here if type is kOatClassSomeCompiled?
    625       if (options_.list_classes_) continue;
    626       if (!DumpOatClass(&vios, oat_class, *dex_file, class_def, &stop_analysis)) {
    627         success = false;
    628       }
    629       if (stop_analysis) {
    630         os << std::flush;
    631         return success;
    632       }
    633     }
    634 
    635     os << std::flush;
    636     return success;
    637   }
    638 
    639   bool ExportDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) {
    640     std::string error_msg;
    641     std::string dex_file_location = oat_dex_file.GetDexFileLocation();
    642 
    643     const DexFile* const dex_file = OpenDexFile(&oat_dex_file, &error_msg);
    644     if (dex_file == nullptr) {
    645       os << "Failed to open dex file '" << dex_file_location << "': " << error_msg;
    646       return false;
    647     }
    648     size_t fsize = oat_dex_file.FileSize();
    649 
    650     // Some quick checks just in case
    651     if (fsize == 0 || fsize < sizeof(DexFile::Header)) {
    652       os << "Invalid dex file\n";
    653       return false;
    654     }
    655 
    656     // Verify output directory exists
    657     if (!OS::DirectoryExists(options_.export_dex_location_)) {
    658       // TODO: Extend OS::DirectoryExists if symlink support is required
    659       os << options_.export_dex_location_ << " output directory not found or symlink\n";
    660       return false;
    661     }
    662 
    663     // Beautify path names
    664     if (dex_file_location.size() > PATH_MAX || dex_file_location.size() <= 0) {
    665       return false;
    666     }
    667 
    668     std::string dex_orig_name;
    669     size_t dex_orig_pos = dex_file_location.rfind('/');
    670     if (dex_orig_pos == std::string::npos)
    671       dex_orig_name = dex_file_location;
    672     else
    673       dex_orig_name = dex_file_location.substr(dex_orig_pos + 1);
    674 
    675     // A more elegant approach to efficiently name user installed apps is welcome
    676     if (dex_orig_name.size() == 8 && !dex_orig_name.compare("base.apk")) {
    677       dex_file_location.erase(dex_orig_pos, strlen("base.apk") + 1);
    678       size_t apk_orig_pos = dex_file_location.rfind('/');
    679       if (apk_orig_pos != std::string::npos) {
    680         dex_orig_name = dex_file_location.substr(++apk_orig_pos);
    681       }
    682     }
    683 
    684     std::string out_dex_path(options_.export_dex_location_);
    685     if (out_dex_path.back() != '/') {
    686       out_dex_path.append("/");
    687     }
    688     out_dex_path.append(dex_orig_name);
    689     out_dex_path.append("_export.dex");
    690     if (out_dex_path.length() > PATH_MAX) {
    691       return false;
    692     }
    693 
    694     std::unique_ptr<File> file(OS::CreateEmptyFile(out_dex_path.c_str()));
    695     if (file.get() == nullptr) {
    696       os << "Failed to open output dex file " << out_dex_path;
    697       return false;
    698     }
    699 
    700     if (!file->WriteFully(dex_file->Begin(), fsize)) {
    701       os << "Failed to write dex file";
    702       file->Erase();
    703       return false;
    704     }
    705 
    706     if (file->FlushCloseOrErase() != 0) {
    707       os << "Flush and close failed";
    708       return false;
    709     }
    710 
    711     os << StringPrintf("Dex file exported at %s (%zd bytes)\n", out_dex_path.c_str(), fsize);
    712     os << std::flush;
    713 
    714     return true;
    715   }
    716 
    717   static void SkipAllFields(ClassDataItemIterator& it) {
    718     while (it.HasNextStaticField()) {
    719       it.Next();
    720     }
    721     while (it.HasNextInstanceField()) {
    722       it.Next();
    723     }
    724   }
    725 
    726   bool DumpOatClass(VariableIndentationOutputStream* vios,
    727                     const OatFile::OatClass& oat_class, const DexFile& dex_file,
    728                     const DexFile::ClassDef& class_def, bool* stop_analysis) {
    729     bool success = true;
    730     bool addr_found = false;
    731     const uint8_t* class_data = dex_file.GetClassData(class_def);
    732     if (class_data == nullptr) {  // empty class such as a marker interface?
    733       vios->Stream() << std::flush;
    734       return success;
    735     }
    736     ClassDataItemIterator it(dex_file, class_data);
    737     SkipAllFields(it);
    738     uint32_t class_method_index = 0;
    739     while (it.HasNextDirectMethod()) {
    740       if (!DumpOatMethod(vios, class_def, class_method_index, oat_class, dex_file,
    741                          it.GetMemberIndex(), it.GetMethodCodeItem(),
    742                          it.GetRawMemberAccessFlags(), &addr_found)) {
    743         success = false;
    744       }
    745       if (addr_found) {
    746         *stop_analysis = true;
    747         return success;
    748       }
    749       class_method_index++;
    750       it.Next();
    751     }
    752     while (it.HasNextVirtualMethod()) {
    753       if (!DumpOatMethod(vios, class_def, class_method_index, oat_class, dex_file,
    754                          it.GetMemberIndex(), it.GetMethodCodeItem(),
    755                          it.GetRawMemberAccessFlags(), &addr_found)) {
    756         success = false;
    757       }
    758       if (addr_found) {
    759         *stop_analysis = true;
    760         return success;
    761       }
    762       class_method_index++;
    763       it.Next();
    764     }
    765     DCHECK(!it.HasNext());
    766     vios->Stream() << std::flush;
    767     return success;
    768   }
    769 
    770   static constexpr uint32_t kPrologueBytes = 16;
    771 
    772   // When this was picked, the largest arm method was 55,256 bytes and arm64 was 50,412 bytes.
    773   static constexpr uint32_t kMaxCodeSize = 100 * 1000;
    774 
    775   bool DumpOatMethod(VariableIndentationOutputStream* vios,
    776                      const DexFile::ClassDef& class_def,
    777                      uint32_t class_method_index,
    778                      const OatFile::OatClass& oat_class, const DexFile& dex_file,
    779                      uint32_t dex_method_idx, const DexFile::CodeItem* code_item,
    780                      uint32_t method_access_flags, bool* addr_found) {
    781     bool success = true;
    782 
    783     // TODO: Support regex
    784     std::string method_name = dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
    785     if (method_name.find(options_.method_filter_) == std::string::npos) {
    786       return success;
    787     }
    788 
    789     std::string pretty_method = PrettyMethod(dex_method_idx, dex_file, true);
    790     vios->Stream() << StringPrintf("%d: %s (dex_method_idx=%d)\n",
    791                                    class_method_index, pretty_method.c_str(),
    792                                    dex_method_idx);
    793     if (options_.list_methods_) return success;
    794 
    795     uint32_t oat_method_offsets_offset = oat_class.GetOatMethodOffsetsOffset(class_method_index);
    796     const OatMethodOffsets* oat_method_offsets = oat_class.GetOatMethodOffsets(class_method_index);
    797     const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_index);
    798     uint32_t code_offset = oat_method.GetCodeOffset();
    799     uint32_t code_size = oat_method.GetQuickCodeSize();
    800     if (resolved_addr2instr_ != 0) {
    801       if (resolved_addr2instr_ > code_offset + code_size) {
    802         return success;
    803       } else {
    804         *addr_found = true;  // stop analyzing file at next iteration
    805       }
    806     }
    807 
    808     // Everything below is indented at least once.
    809     ScopedIndentation indent1(vios);
    810 
    811     {
    812       vios->Stream() << "DEX CODE:\n";
    813       ScopedIndentation indent2(vios);
    814       DumpDexCode(vios->Stream(), dex_file, code_item);
    815     }
    816 
    817     std::unique_ptr<StackHandleScope<1>> hs;
    818     std::unique_ptr<verifier::MethodVerifier> verifier;
    819     if (Runtime::Current() != nullptr) {
    820       // We need to have the handle scope stay live until after the verifier since the verifier has
    821       // a handle to the dex cache from hs.
    822       hs.reset(new StackHandleScope<1>(Thread::Current()));
    823       vios->Stream() << "VERIFIER TYPE ANALYSIS:\n";
    824       ScopedIndentation indent2(vios);
    825       verifier.reset(DumpVerifier(vios, hs.get(),
    826                                   dex_method_idx, &dex_file, class_def, code_item,
    827                                   method_access_flags));
    828     }
    829     {
    830       vios->Stream() << "OatMethodOffsets ";
    831       if (options_.absolute_addresses_) {
    832         vios->Stream() << StringPrintf("%p ", oat_method_offsets);
    833       }
    834       vios->Stream() << StringPrintf("(offset=0x%08x)\n", oat_method_offsets_offset);
    835       if (oat_method_offsets_offset > oat_file_.Size()) {
    836         vios->Stream() << StringPrintf(
    837             "WARNING: oat method offsets offset 0x%08x is past end of file 0x%08zx.\n",
    838             oat_method_offsets_offset, oat_file_.Size());
    839         // If we can't read OatMethodOffsets, the rest of the data is dangerous to read.
    840         vios->Stream() << std::flush;
    841         return false;
    842       }
    843 
    844       ScopedIndentation indent2(vios);
    845       vios->Stream() << StringPrintf("code_offset: 0x%08x ", code_offset);
    846       uint32_t aligned_code_begin = AlignCodeOffset(oat_method.GetCodeOffset());
    847       if (aligned_code_begin > oat_file_.Size()) {
    848         vios->Stream() << StringPrintf("WARNING: "
    849                                        "code offset 0x%08x is past end of file 0x%08zx.\n",
    850                                        aligned_code_begin, oat_file_.Size());
    851         success = false;
    852       }
    853       vios->Stream() << "\n";
    854     }
    855     {
    856       vios->Stream() << "OatQuickMethodHeader ";
    857       uint32_t method_header_offset = oat_method.GetOatQuickMethodHeaderOffset();
    858       const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
    859 
    860       if (options_.absolute_addresses_) {
    861         vios->Stream() << StringPrintf("%p ", method_header);
    862       }
    863       vios->Stream() << StringPrintf("(offset=0x%08x)\n", method_header_offset);
    864       if (method_header_offset > oat_file_.Size()) {
    865         vios->Stream() << StringPrintf(
    866             "WARNING: oat quick method header offset 0x%08x is past end of file 0x%08zx.\n",
    867             method_header_offset, oat_file_.Size());
    868         // If we can't read the OatQuickMethodHeader, the rest of the data is dangerous to read.
    869         vios->Stream() << std::flush;
    870         return false;
    871       }
    872 
    873       ScopedIndentation indent2(vios);
    874       vios->Stream() << "vmap_table: ";
    875       if (options_.absolute_addresses_) {
    876         vios->Stream() << StringPrintf("%p ", oat_method.GetVmapTable());
    877       }
    878       uint32_t vmap_table_offset = oat_method.GetVmapTableOffset();
    879       vios->Stream() << StringPrintf("(offset=0x%08x)\n", vmap_table_offset);
    880       if (vmap_table_offset > oat_file_.Size()) {
    881         vios->Stream() << StringPrintf("WARNING: "
    882                                        "vmap table offset 0x%08x is past end of file 0x%08zx. "
    883                                        "vmap table offset was loaded from offset 0x%08x.\n",
    884                                        vmap_table_offset, oat_file_.Size(),
    885                                        oat_method.GetVmapTableOffsetOffset());
    886         success = false;
    887       } else if (options_.dump_vmap_) {
    888         DumpVmapData(vios, oat_method, code_item);
    889       }
    890     }
    891     {
    892       vios->Stream() << "QuickMethodFrameInfo\n";
    893 
    894       ScopedIndentation indent2(vios);
    895       vios->Stream()
    896           << StringPrintf("frame_size_in_bytes: %zd\n", oat_method.GetFrameSizeInBytes());
    897       vios->Stream() << StringPrintf("core_spill_mask: 0x%08x ", oat_method.GetCoreSpillMask());
    898       DumpSpillMask(vios->Stream(), oat_method.GetCoreSpillMask(), false);
    899       vios->Stream() << "\n";
    900       vios->Stream() << StringPrintf("fp_spill_mask: 0x%08x ", oat_method.GetFpSpillMask());
    901       DumpSpillMask(vios->Stream(), oat_method.GetFpSpillMask(), true);
    902       vios->Stream() << "\n";
    903     }
    904     {
    905       // Based on spill masks from QuickMethodFrameInfo so placed
    906       // after it is dumped, but useful for understanding quick
    907       // code, so dumped here.
    908       ScopedIndentation indent2(vios);
    909       DumpVregLocations(vios->Stream(), oat_method, code_item);
    910     }
    911     {
    912       vios->Stream() << "CODE: ";
    913       uint32_t code_size_offset = oat_method.GetQuickCodeSizeOffset();
    914       if (code_size_offset > oat_file_.Size()) {
    915         ScopedIndentation indent2(vios);
    916         vios->Stream() << StringPrintf("WARNING: "
    917                                        "code size offset 0x%08x is past end of file 0x%08zx.",
    918                                        code_size_offset, oat_file_.Size());
    919         success = false;
    920       } else {
    921         const void* code = oat_method.GetQuickCode();
    922         uint32_t aligned_code_begin = AlignCodeOffset(code_offset);
    923         uint64_t aligned_code_end = aligned_code_begin + code_size;
    924 
    925         if (options_.absolute_addresses_) {
    926           vios->Stream() << StringPrintf("%p ", code);
    927         }
    928         vios->Stream() << StringPrintf("(code_offset=0x%08x size_offset=0x%08x size=%u)%s\n",
    929                                        code_offset,
    930                                        code_size_offset,
    931                                        code_size,
    932                                        code != nullptr ? "..." : "");
    933 
    934         ScopedIndentation indent2(vios);
    935         if (aligned_code_begin > oat_file_.Size()) {
    936           vios->Stream() << StringPrintf("WARNING: "
    937                                          "start of code at 0x%08x is past end of file 0x%08zx.",
    938                                          aligned_code_begin, oat_file_.Size());
    939           success = false;
    940         } else if (aligned_code_end > oat_file_.Size()) {
    941           vios->Stream() << StringPrintf(
    942               "WARNING: "
    943               "end of code at 0x%08" PRIx64 " is past end of file 0x%08zx. "
    944               "code size is 0x%08x loaded from offset 0x%08x.\n",
    945               aligned_code_end, oat_file_.Size(),
    946               code_size, code_size_offset);
    947           success = false;
    948           if (options_.disassemble_code_) {
    949             if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
    950               DumpCode(vios, oat_method, code_item, true, kPrologueBytes);
    951             }
    952           }
    953         } else if (code_size > kMaxCodeSize) {
    954           vios->Stream() << StringPrintf(
    955               "WARNING: "
    956               "code size %d is bigger than max expected threshold of %d. "
    957               "code size is 0x%08x loaded from offset 0x%08x.\n",
    958               code_size, kMaxCodeSize,
    959               code_size, code_size_offset);
    960           success = false;
    961           if (options_.disassemble_code_) {
    962             if (code_size_offset + kPrologueBytes <= oat_file_.Size()) {
    963               DumpCode(vios, oat_method, code_item, true, kPrologueBytes);
    964             }
    965           }
    966         } else if (options_.disassemble_code_) {
    967           DumpCode(vios, oat_method, code_item, !success, 0);
    968         }
    969       }
    970     }
    971     vios->Stream() << std::flush;
    972     return success;
    973   }
    974 
    975   void DumpSpillMask(std::ostream& os, uint32_t spill_mask, bool is_float) {
    976     if (spill_mask == 0) {
    977       return;
    978     }
    979     os << "(";
    980     for (size_t i = 0; i < 32; i++) {
    981       if ((spill_mask & (1 << i)) != 0) {
    982         if (is_float) {
    983           os << "fr" << i;
    984         } else {
    985           os << "r" << i;
    986         }
    987         spill_mask ^= 1 << i;  // clear bit
    988         if (spill_mask != 0) {
    989           os << ", ";
    990         } else {
    991           break;
    992         }
    993       }
    994     }
    995     os << ")";
    996   }
    997 
    998   // Display data stored at the the vmap offset of an oat method.
    999   void DumpVmapData(VariableIndentationOutputStream* vios,
   1000                     const OatFile::OatMethod& oat_method,
   1001                     const DexFile::CodeItem* code_item) {
   1002     if (IsMethodGeneratedByOptimizingCompiler(oat_method, code_item)) {
   1003       // The optimizing compiler outputs its CodeInfo data in the vmap table.
   1004       const void* raw_code_info = oat_method.GetVmapTable();
   1005       if (raw_code_info != nullptr) {
   1006         CodeInfo code_info(raw_code_info);
   1007         DCHECK(code_item != nullptr);
   1008         ScopedIndentation indent1(vios);
   1009         DumpCodeInfo(vios, code_info, oat_method, *code_item);
   1010       }
   1011     } else if (IsMethodGeneratedByDexToDexCompiler(oat_method, code_item)) {
   1012       // We don't encode the size in the table, so just emit that we have quickened
   1013       // information.
   1014       ScopedIndentation indent(vios);
   1015       vios->Stream() << "quickened data\n";
   1016     } else {
   1017       // Otherwise, there is nothing to display.
   1018     }
   1019   }
   1020 
   1021   // Display a CodeInfo object emitted by the optimizing compiler.
   1022   void DumpCodeInfo(VariableIndentationOutputStream* vios,
   1023                     const CodeInfo& code_info,
   1024                     const OatFile::OatMethod& oat_method,
   1025                     const DexFile::CodeItem& code_item) {
   1026     code_info.Dump(vios,
   1027                    oat_method.GetCodeOffset(),
   1028                    code_item.registers_size_,
   1029                    options_.dump_code_info_stack_maps_);
   1030   }
   1031 
   1032   void DumpVregLocations(std::ostream& os, const OatFile::OatMethod& oat_method,
   1033                          const DexFile::CodeItem* code_item) {
   1034     if (code_item != nullptr) {
   1035       size_t num_locals_ins = code_item->registers_size_;
   1036       size_t num_ins = code_item->ins_size_;
   1037       size_t num_locals = num_locals_ins - num_ins;
   1038       size_t num_outs = code_item->outs_size_;
   1039 
   1040       os << "vr_stack_locations:";
   1041       for (size_t reg = 0; reg <= num_locals_ins; reg++) {
   1042         // For readability, delimit the different kinds of VRs.
   1043         if (reg == num_locals_ins) {
   1044           os << "\n\tmethod*:";
   1045         } else if (reg == num_locals && num_ins > 0) {
   1046           os << "\n\tins:";
   1047         } else if (reg == 0 && num_locals > 0) {
   1048           os << "\n\tlocals:";
   1049         }
   1050 
   1051         uint32_t offset = StackVisitor::GetVRegOffsetFromQuickCode(
   1052             code_item,
   1053             oat_method.GetCoreSpillMask(),
   1054             oat_method.GetFpSpillMask(),
   1055             oat_method.GetFrameSizeInBytes(),
   1056             reg,
   1057             GetInstructionSet());
   1058         os << " v" << reg << "[sp + #" << offset << "]";
   1059       }
   1060 
   1061       for (size_t out_reg = 0; out_reg < num_outs; out_reg++) {
   1062         if (out_reg == 0) {
   1063           os << "\n\touts:";
   1064         }
   1065 
   1066         uint32_t offset = StackVisitor::GetOutVROffset(out_reg, GetInstructionSet());
   1067         os << " v" << out_reg << "[sp + #" << offset << "]";
   1068       }
   1069 
   1070       os << "\n";
   1071     }
   1072   }
   1073 
   1074   void DumpDexCode(std::ostream& os, const DexFile& dex_file, const DexFile::CodeItem* code_item) {
   1075     if (code_item != nullptr) {
   1076       size_t i = 0;
   1077       while (i < code_item->insns_size_in_code_units_) {
   1078         const Instruction* instruction = Instruction::At(&code_item->insns_[i]);
   1079         os << StringPrintf("0x%04zx: ", i) << instruction->DumpHexLE(5)
   1080            << StringPrintf("\t| %s\n", instruction->DumpString(&dex_file).c_str());
   1081         i += instruction->SizeInCodeUnits();
   1082       }
   1083     }
   1084   }
   1085 
   1086   // Has `oat_method` -- corresponding to the Dex `code_item` -- been compiled by
   1087   // the optimizing compiler?
   1088   static bool IsMethodGeneratedByOptimizingCompiler(const OatFile::OatMethod& oat_method,
   1089                                                     const DexFile::CodeItem* code_item) {
   1090     // If the native GC map is null and the Dex `code_item` is not
   1091     // null, then this method has been compiled with the optimizing
   1092     // compiler.
   1093     return oat_method.GetQuickCode() != nullptr &&
   1094            oat_method.GetVmapTable() != nullptr &&
   1095            code_item != nullptr;
   1096   }
   1097 
   1098   // Has `oat_method` -- corresponding to the Dex `code_item` -- been compiled by
   1099   // the dextodex compiler?
   1100   static bool IsMethodGeneratedByDexToDexCompiler(const OatFile::OatMethod& oat_method,
   1101                                                   const DexFile::CodeItem* code_item) {
   1102     // If the quick code is null, the Dex `code_item` is not
   1103     // null, and the vmap table is not null, then this method has been compiled
   1104     // with the dextodex compiler.
   1105     return oat_method.GetQuickCode() == nullptr &&
   1106            oat_method.GetVmapTable() != nullptr &&
   1107            code_item != nullptr;
   1108   }
   1109 
   1110   verifier::MethodVerifier* DumpVerifier(VariableIndentationOutputStream* vios,
   1111                                          StackHandleScope<1>* hs,
   1112                                          uint32_t dex_method_idx,
   1113                                          const DexFile* dex_file,
   1114                                          const DexFile::ClassDef& class_def,
   1115                                          const DexFile::CodeItem* code_item,
   1116                                          uint32_t method_access_flags) {
   1117     if ((method_access_flags & kAccNative) == 0) {
   1118       ScopedObjectAccess soa(Thread::Current());
   1119       Runtime* const runtime = Runtime::Current();
   1120       Handle<mirror::DexCache> dex_cache(
   1121           hs->NewHandle(runtime->GetClassLinker()->RegisterDexFile(*dex_file, nullptr)));
   1122       DCHECK(options_.class_loader_ != nullptr);
   1123       return verifier::MethodVerifier::VerifyMethodAndDump(
   1124           soa.Self(), vios, dex_method_idx, dex_file, dex_cache, *options_.class_loader_,
   1125           &class_def, code_item, nullptr, method_access_flags);
   1126     }
   1127 
   1128     return nullptr;
   1129   }
   1130 
   1131   // The StackMapsHelper provides the stack maps in the native PC order.
   1132   // For identical native PCs, the order from the CodeInfo is preserved.
   1133   class StackMapsHelper {
   1134    public:
   1135     explicit StackMapsHelper(const uint8_t* raw_code_info)
   1136         : code_info_(raw_code_info),
   1137           encoding_(code_info_.ExtractEncoding()),
   1138           number_of_stack_maps_(code_info_.GetNumberOfStackMaps(encoding_)),
   1139           indexes_(),
   1140           offset_(static_cast<size_t>(-1)),
   1141           stack_map_index_(0u) {
   1142       if (number_of_stack_maps_ != 0u) {
   1143         // Check if native PCs are ordered.
   1144         bool ordered = true;
   1145         StackMap last = code_info_.GetStackMapAt(0u, encoding_);
   1146         for (size_t i = 1; i != number_of_stack_maps_; ++i) {
   1147           StackMap current = code_info_.GetStackMapAt(i, encoding_);
   1148           if (last.GetNativePcOffset(encoding_.stack_map_encoding) >
   1149               current.GetNativePcOffset(encoding_.stack_map_encoding)) {
   1150             ordered = false;
   1151             break;
   1152           }
   1153           last = current;
   1154         }
   1155         if (!ordered) {
   1156           // Create indirection indexes for access in native PC order. We do not optimize
   1157           // for the fact that there can currently be only two separately ordered ranges,
   1158           // namely normal stack maps and catch-point stack maps.
   1159           indexes_.resize(number_of_stack_maps_);
   1160           std::iota(indexes_.begin(), indexes_.end(), 0u);
   1161           std::sort(indexes_.begin(),
   1162                     indexes_.end(),
   1163                     [this](size_t lhs, size_t rhs) {
   1164                       StackMap left = code_info_.GetStackMapAt(lhs, encoding_);
   1165                       uint32_t left_pc = left.GetNativePcOffset(encoding_.stack_map_encoding);
   1166                       StackMap right = code_info_.GetStackMapAt(rhs, encoding_);
   1167                       uint32_t right_pc = right.GetNativePcOffset(encoding_.stack_map_encoding);
   1168                       // If the PCs are the same, compare indexes to preserve the original order.
   1169                       return (left_pc < right_pc) || (left_pc == right_pc && lhs < rhs);
   1170                     });
   1171         }
   1172         offset_ = GetStackMapAt(0).GetNativePcOffset(encoding_.stack_map_encoding);
   1173       }
   1174     }
   1175 
   1176     const CodeInfo& GetCodeInfo() const {
   1177       return code_info_;
   1178     }
   1179 
   1180     const CodeInfoEncoding& GetEncoding() const {
   1181       return encoding_;
   1182     }
   1183 
   1184     size_t GetOffset() const {
   1185       return offset_;
   1186     }
   1187 
   1188     StackMap GetStackMap() const {
   1189       return GetStackMapAt(stack_map_index_);
   1190     }
   1191 
   1192     void Next() {
   1193       ++stack_map_index_;
   1194       offset_ = (stack_map_index_ == number_of_stack_maps_)
   1195           ? static_cast<size_t>(-1)
   1196           : GetStackMapAt(stack_map_index_).GetNativePcOffset(encoding_.stack_map_encoding);
   1197     }
   1198 
   1199    private:
   1200     StackMap GetStackMapAt(size_t i) const {
   1201       if (!indexes_.empty()) {
   1202         i = indexes_[i];
   1203       }
   1204       DCHECK_LT(i, number_of_stack_maps_);
   1205       return code_info_.GetStackMapAt(i, encoding_);
   1206     }
   1207 
   1208     const CodeInfo code_info_;
   1209     const CodeInfoEncoding encoding_;
   1210     const size_t number_of_stack_maps_;
   1211     dchecked_vector<size_t> indexes_;  // Used if stack map native PCs are not ordered.
   1212     size_t offset_;
   1213     size_t stack_map_index_;
   1214   };
   1215 
   1216   void DumpCode(VariableIndentationOutputStream* vios,
   1217                 const OatFile::OatMethod& oat_method, const DexFile::CodeItem* code_item,
   1218                 bool bad_input, size_t code_size) {
   1219     const void* quick_code = oat_method.GetQuickCode();
   1220 
   1221     if (code_size == 0) {
   1222       code_size = oat_method.GetQuickCodeSize();
   1223     }
   1224     if (code_size == 0 || quick_code == nullptr) {
   1225       vios->Stream() << "NO CODE!\n";
   1226       return;
   1227     } else if (!bad_input && IsMethodGeneratedByOptimizingCompiler(oat_method, code_item)) {
   1228       // The optimizing compiler outputs its CodeInfo data in the vmap table.
   1229       StackMapsHelper helper(oat_method.GetVmapTable());
   1230       const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
   1231       size_t offset = 0;
   1232       while (offset < code_size) {
   1233         offset += disassembler_->Dump(vios->Stream(), quick_native_pc + offset);
   1234         if (offset == helper.GetOffset()) {
   1235           ScopedIndentation indent1(vios);
   1236           StackMap stack_map = helper.GetStackMap();
   1237           DCHECK(stack_map.IsValid());
   1238           stack_map.Dump(vios,
   1239                          helper.GetCodeInfo(),
   1240                          helper.GetEncoding(),
   1241                          oat_method.GetCodeOffset(),
   1242                          code_item->registers_size_);
   1243           do {
   1244             helper.Next();
   1245             // There may be multiple stack maps at a given PC. We display only the first one.
   1246           } while (offset == helper.GetOffset());
   1247         }
   1248         DCHECK_LT(offset, helper.GetOffset());
   1249       }
   1250     } else {
   1251       const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
   1252       size_t offset = 0;
   1253       while (offset < code_size) {
   1254         offset += disassembler_->Dump(vios->Stream(), quick_native_pc + offset);
   1255       }
   1256     }
   1257   }
   1258 
   1259   const OatFile& oat_file_;
   1260   const std::vector<const OatFile::OatDexFile*> oat_dex_files_;
   1261   const OatDumperOptions& options_;
   1262   uint32_t resolved_addr2instr_;
   1263   InstructionSet instruction_set_;
   1264   std::set<uintptr_t> offsets_;
   1265   Disassembler* disassembler_;
   1266 };
   1267 
   1268 class ImageDumper {
   1269  public:
   1270   ImageDumper(std::ostream* os,
   1271               gc::space::ImageSpace& image_space,
   1272               const ImageHeader& image_header,
   1273               OatDumperOptions* oat_dumper_options)
   1274       : os_(os),
   1275         vios_(os),
   1276         indent1_(&vios_),
   1277         image_space_(image_space),
   1278         image_header_(image_header),
   1279         oat_dumper_options_(oat_dumper_options) {}
   1280 
   1281   bool Dump() SHARED_REQUIRES(Locks::mutator_lock_) {
   1282     std::ostream& os = *os_;
   1283     std::ostream& indent_os = vios_.Stream();
   1284 
   1285     os << "MAGIC: " << image_header_.GetMagic() << "\n\n";
   1286 
   1287     os << "IMAGE LOCATION: " << image_space_.GetImageLocation() << "\n\n";
   1288 
   1289     os << "IMAGE BEGIN: " << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n";
   1290 
   1291     os << "IMAGE SIZE: " << image_header_.GetImageSize() << "\n\n";
   1292 
   1293     for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
   1294       auto section = static_cast<ImageHeader::ImageSections>(i);
   1295       os << "IMAGE SECTION " << section << ": " << image_header_.GetImageSection(section) << "\n\n";
   1296     }
   1297 
   1298     os << "OAT CHECKSUM: " << StringPrintf("0x%08x\n\n", image_header_.GetOatChecksum());
   1299 
   1300     os << "OAT FILE BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatFileBegin()) << "\n\n";
   1301 
   1302     os << "OAT DATA BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatDataBegin()) << "\n\n";
   1303 
   1304     os << "OAT DATA END:" << reinterpret_cast<void*>(image_header_.GetOatDataEnd()) << "\n\n";
   1305 
   1306     os << "OAT FILE END:" << reinterpret_cast<void*>(image_header_.GetOatFileEnd()) << "\n\n";
   1307 
   1308     os << "PATCH DELTA:" << image_header_.GetPatchDelta() << "\n\n";
   1309 
   1310     os << "COMPILE PIC: " << (image_header_.CompilePic() ? "yes" : "no") << "\n\n";
   1311 
   1312     {
   1313       os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n";
   1314       static_assert(arraysize(image_roots_descriptions_) ==
   1315           static_cast<size_t>(ImageHeader::kImageRootsMax), "sizes must match");
   1316       for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
   1317         ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
   1318         const char* image_root_description = image_roots_descriptions_[i];
   1319         mirror::Object* image_root_object = image_header_.GetImageRoot(image_root);
   1320         indent_os << StringPrintf("%s: %p\n", image_root_description, image_root_object);
   1321         if (image_root_object->IsObjectArray()) {
   1322           mirror::ObjectArray<mirror::Object>* image_root_object_array
   1323               = image_root_object->AsObjectArray<mirror::Object>();
   1324           ScopedIndentation indent2(&vios_);
   1325           for (int j = 0; j < image_root_object_array->GetLength(); j++) {
   1326             mirror::Object* value = image_root_object_array->Get(j);
   1327             size_t run = 0;
   1328             for (int32_t k = j + 1; k < image_root_object_array->GetLength(); k++) {
   1329               if (value == image_root_object_array->Get(k)) {
   1330                 run++;
   1331               } else {
   1332                 break;
   1333               }
   1334             }
   1335             if (run == 0) {
   1336               indent_os << StringPrintf("%d: ", j);
   1337             } else {
   1338               indent_os << StringPrintf("%d to %zd: ", j, j + run);
   1339               j = j + run;
   1340             }
   1341             if (value != nullptr) {
   1342               PrettyObjectValue(indent_os, value->GetClass(), value);
   1343             } else {
   1344               indent_os << j << ": null\n";
   1345             }
   1346           }
   1347         }
   1348       }
   1349     }
   1350 
   1351     {
   1352       os << "METHOD ROOTS\n";
   1353       static_assert(arraysize(image_methods_descriptions_) ==
   1354           static_cast<size_t>(ImageHeader::kImageMethodsCount), "sizes must match");
   1355       for (int i = 0; i < ImageHeader::kImageMethodsCount; i++) {
   1356         auto image_root = static_cast<ImageHeader::ImageMethod>(i);
   1357         const char* description = image_methods_descriptions_[i];
   1358         auto* image_method = image_header_.GetImageMethod(image_root);
   1359         indent_os << StringPrintf("%s: %p\n", description, image_method);
   1360       }
   1361     }
   1362     os << "\n";
   1363 
   1364     Runtime* const runtime = Runtime::Current();
   1365     ClassLinker* class_linker = runtime->GetClassLinker();
   1366     std::string image_filename = image_space_.GetImageFilename();
   1367     std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(image_filename);
   1368     os << "OAT LOCATION: " << oat_location;
   1369     os << "\n";
   1370     std::string error_msg;
   1371     const OatFile* oat_file = image_space_.GetOatFile();
   1372     if (oat_file == nullptr) {
   1373       oat_file = runtime->GetOatFileManager().FindOpenedOatFileFromOatLocation(oat_location);
   1374     }
   1375     if (oat_file == nullptr) {
   1376       oat_file = OatFile::Open(oat_location,
   1377                                oat_location,
   1378                                nullptr,
   1379                                nullptr,
   1380                                false,
   1381                                /*low_4gb*/false,
   1382                                nullptr,
   1383                                &error_msg);
   1384     }
   1385     if (oat_file == nullptr) {
   1386       os << "OAT FILE NOT FOUND: " << error_msg << "\n";
   1387       return EXIT_FAILURE;
   1388     }
   1389     os << "\n";
   1390 
   1391     stats_.oat_file_bytes = oat_file->Size();
   1392 
   1393     oat_dumper_.reset(new OatDumper(*oat_file, *oat_dumper_options_));
   1394 
   1395     for (const OatFile::OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) {
   1396       CHECK(oat_dex_file != nullptr);
   1397       stats_.oat_dex_file_sizes.push_back(std::make_pair(oat_dex_file->GetDexFileLocation(),
   1398                                                          oat_dex_file->FileSize()));
   1399     }
   1400 
   1401     os << "OBJECTS:\n" << std::flush;
   1402 
   1403     // Loop through the image space and dump its objects.
   1404     gc::Heap* heap = runtime->GetHeap();
   1405     Thread* self = Thread::Current();
   1406     {
   1407       {
   1408         WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
   1409         heap->FlushAllocStack();
   1410       }
   1411       // Since FlushAllocStack() above resets the (active) allocation
   1412       // stack. Need to revoke the thread-local allocation stacks that
   1413       // point into it.
   1414       ScopedThreadSuspension sts(self, kNative);
   1415       ScopedSuspendAll ssa(__FUNCTION__);
   1416       heap->RevokeAllThreadLocalAllocationStacks(self);
   1417     }
   1418     {
   1419       // Mark dex caches.
   1420       dex_caches_.clear();
   1421       {
   1422         ReaderMutexLock mu(self, *class_linker->DexLock());
   1423         for (const ClassLinker::DexCacheData& data : class_linker->GetDexCachesData()) {
   1424           mirror::DexCache* dex_cache =
   1425               down_cast<mirror::DexCache*>(self->DecodeJObject(data.weak_root));
   1426           if (dex_cache != nullptr) {
   1427             dex_caches_.insert(dex_cache);
   1428           }
   1429         }
   1430       }
   1431       ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
   1432       // Dump the normal objects before ArtMethods.
   1433       image_space_.GetLiveBitmap()->Walk(ImageDumper::Callback, this);
   1434       indent_os << "\n";
   1435       // TODO: Dump fields.
   1436       // Dump methods after.
   1437       DumpArtMethodVisitor visitor(this);
   1438       image_header_.VisitPackedArtMethods(&visitor,
   1439                                           image_space_.Begin(),
   1440                                           image_header_.GetPointerSize());
   1441       // Dump the large objects separately.
   1442       heap->GetLargeObjectsSpace()->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
   1443       indent_os << "\n";
   1444     }
   1445     os << "STATS:\n" << std::flush;
   1446     std::unique_ptr<File> file(OS::OpenFileForReading(image_filename.c_str()));
   1447     size_t data_size = image_header_.GetDataSize();  // stored size in file.
   1448     if (file == nullptr) {
   1449       LOG(WARNING) << "Failed to find image in " << image_filename;
   1450     } else {
   1451       stats_.file_bytes = file->GetLength();
   1452       // If the image is compressed, adjust to decompressed size.
   1453       size_t uncompressed_size = image_header_.GetImageSize() - sizeof(ImageHeader);
   1454       if (image_header_.GetStorageMode() == ImageHeader::kStorageModeUncompressed) {
   1455         DCHECK_EQ(uncompressed_size, data_size) << "Sizes should match for uncompressed image";
   1456       }
   1457       stats_.file_bytes += uncompressed_size - data_size;
   1458     }
   1459     size_t header_bytes = sizeof(ImageHeader);
   1460     const auto& object_section = image_header_.GetImageSection(ImageHeader::kSectionObjects);
   1461     const auto& field_section = image_header_.GetImageSection(ImageHeader::kSectionArtFields);
   1462     const auto& method_section = image_header_.GetMethodsSection();
   1463     const auto& dex_cache_arrays_section = image_header_.GetImageSection(
   1464         ImageHeader::kSectionDexCacheArrays);
   1465     const auto& intern_section = image_header_.GetImageSection(
   1466         ImageHeader::kSectionInternedStrings);
   1467     const auto& class_table_section = image_header_.GetImageSection(
   1468         ImageHeader::kSectionClassTable);
   1469     const auto& bitmap_section = image_header_.GetImageSection(ImageHeader::kSectionImageBitmap);
   1470 
   1471     stats_.header_bytes = header_bytes;
   1472 
   1473     // Objects are kObjectAlignment-aligned.
   1474     // CHECK_EQ(RoundUp(header_bytes, kObjectAlignment), object_section.Offset());
   1475     if (object_section.Offset() > header_bytes) {
   1476       stats_.alignment_bytes += object_section.Offset() - header_bytes;
   1477     }
   1478 
   1479     // Field section is 4-byte aligned.
   1480     constexpr size_t kFieldSectionAlignment = 4U;
   1481     uint32_t end_objects = object_section.Offset() + object_section.Size();
   1482     CHECK_EQ(RoundUp(end_objects, kFieldSectionAlignment), field_section.Offset());
   1483     stats_.alignment_bytes += field_section.Offset() - end_objects;
   1484 
   1485     // Method section is 4/8 byte aligned depending on target. Just check for 4-byte alignment.
   1486     uint32_t end_fields = field_section.Offset() + field_section.Size();
   1487     CHECK_ALIGNED(method_section.Offset(), 4);
   1488     stats_.alignment_bytes += method_section.Offset() - end_fields;
   1489 
   1490     // Dex cache arrays section is aligned depending on the target. Just check for 4-byte alignment.
   1491     uint32_t end_methods = method_section.Offset() + method_section.Size();
   1492     CHECK_ALIGNED(dex_cache_arrays_section.Offset(), 4);
   1493     stats_.alignment_bytes += dex_cache_arrays_section.Offset() - end_methods;
   1494 
   1495     // Intern table is 8-byte aligned.
   1496     uint32_t end_caches = dex_cache_arrays_section.Offset() + dex_cache_arrays_section.Size();
   1497     CHECK_EQ(RoundUp(end_caches, 8U), intern_section.Offset());
   1498     stats_.alignment_bytes += intern_section.Offset() - end_caches;
   1499 
   1500     // Add space between intern table and class table.
   1501     uint32_t end_intern = intern_section.Offset() + intern_section.Size();
   1502     stats_.alignment_bytes += class_table_section.Offset() - end_intern;
   1503 
   1504     // Add space between end of image data and bitmap. Expect the bitmap to be page-aligned.
   1505     const size_t bitmap_offset = sizeof(ImageHeader) + data_size;
   1506     CHECK_ALIGNED(bitmap_section.Offset(), kPageSize);
   1507     stats_.alignment_bytes += RoundUp(bitmap_offset, kPageSize) - bitmap_offset;
   1508 
   1509     stats_.bitmap_bytes += bitmap_section.Size();
   1510     stats_.art_field_bytes += field_section.Size();
   1511     stats_.art_method_bytes += method_section.Size();
   1512     stats_.dex_cache_arrays_bytes += dex_cache_arrays_section.Size();
   1513     stats_.interned_strings_bytes += intern_section.Size();
   1514     stats_.class_table_bytes += class_table_section.Size();
   1515     stats_.Dump(os, indent_os);
   1516     os << "\n";
   1517 
   1518     os << std::flush;
   1519 
   1520     return oat_dumper_->Dump(os);
   1521   }
   1522 
   1523  private:
   1524   class DumpArtMethodVisitor : public ArtMethodVisitor {
   1525    public:
   1526     explicit DumpArtMethodVisitor(ImageDumper* image_dumper) : image_dumper_(image_dumper) {}
   1527 
   1528     virtual void Visit(ArtMethod* method) OVERRIDE SHARED_REQUIRES(Locks::mutator_lock_) {
   1529       std::ostream& indent_os = image_dumper_->vios_.Stream();
   1530       indent_os << method << " " << " ArtMethod: " << PrettyMethod(method) << "\n";
   1531       image_dumper_->DumpMethod(method, indent_os);
   1532       indent_os << "\n";
   1533     }
   1534 
   1535    private:
   1536     ImageDumper* const image_dumper_;
   1537   };
   1538 
   1539   static void PrettyObjectValue(std::ostream& os, mirror::Class* type, mirror::Object* value)
   1540       SHARED_REQUIRES(Locks::mutator_lock_) {
   1541     CHECK(type != nullptr);
   1542     if (value == nullptr) {
   1543       os << StringPrintf("null   %s\n", PrettyDescriptor(type).c_str());
   1544     } else if (type->IsStringClass()) {
   1545       mirror::String* string = value->AsString();
   1546       os << StringPrintf("%p   String: %s\n", string,
   1547                          PrintableString(string->ToModifiedUtf8().c_str()).c_str());
   1548     } else if (type->IsClassClass()) {
   1549       mirror::Class* klass = value->AsClass();
   1550       os << StringPrintf("%p   Class: %s\n", klass, PrettyDescriptor(klass).c_str());
   1551     } else {
   1552       os << StringPrintf("%p   %s\n", value, PrettyDescriptor(type).c_str());
   1553     }
   1554   }
   1555 
   1556   static void PrintField(std::ostream& os, ArtField* field, mirror::Object* obj)
   1557       SHARED_REQUIRES(Locks::mutator_lock_) {
   1558     os << StringPrintf("%s: ", field->GetName());
   1559     switch (field->GetTypeAsPrimitiveType()) {
   1560       case Primitive::kPrimLong:
   1561         os << StringPrintf("%" PRId64 " (0x%" PRIx64 ")\n", field->Get64(obj), field->Get64(obj));
   1562         break;
   1563       case Primitive::kPrimDouble:
   1564         os << StringPrintf("%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj));
   1565         break;
   1566       case Primitive::kPrimFloat:
   1567         os << StringPrintf("%f (%a)\n", field->GetFloat(obj), field->GetFloat(obj));
   1568         break;
   1569       case Primitive::kPrimInt:
   1570         os << StringPrintf("%d (0x%x)\n", field->Get32(obj), field->Get32(obj));
   1571         break;
   1572       case Primitive::kPrimChar:
   1573         os << StringPrintf("%u (0x%x)\n", field->GetChar(obj), field->GetChar(obj));
   1574         break;
   1575       case Primitive::kPrimShort:
   1576         os << StringPrintf("%d (0x%x)\n", field->GetShort(obj), field->GetShort(obj));
   1577         break;
   1578       case Primitive::kPrimBoolean:
   1579         os << StringPrintf("%s (0x%x)\n", field->GetBoolean(obj)? "true" : "false",
   1580             field->GetBoolean(obj));
   1581         break;
   1582       case Primitive::kPrimByte:
   1583         os << StringPrintf("%d (0x%x)\n", field->GetByte(obj), field->GetByte(obj));
   1584         break;
   1585       case Primitive::kPrimNot: {
   1586         // Get the value, don't compute the type unless it is non-null as we don't want
   1587         // to cause class loading.
   1588         mirror::Object* value = field->GetObj(obj);
   1589         if (value == nullptr) {
   1590           os << StringPrintf("null   %s\n", PrettyDescriptor(field->GetTypeDescriptor()).c_str());
   1591         } else {
   1592           // Grab the field type without causing resolution.
   1593           mirror::Class* field_type = field->GetType<false>();
   1594           if (field_type != nullptr) {
   1595             PrettyObjectValue(os, field_type, value);
   1596           } else {
   1597             os << StringPrintf("%p   %s\n", value,
   1598                                PrettyDescriptor(field->GetTypeDescriptor()).c_str());
   1599           }
   1600         }
   1601         break;
   1602       }
   1603       default:
   1604         os << "unexpected field type: " << field->GetTypeDescriptor() << "\n";
   1605         break;
   1606     }
   1607   }
   1608 
   1609   static void DumpFields(std::ostream& os, mirror::Object* obj, mirror::Class* klass)
   1610       SHARED_REQUIRES(Locks::mutator_lock_) {
   1611     mirror::Class* super = klass->GetSuperClass();
   1612     if (super != nullptr) {
   1613       DumpFields(os, obj, super);
   1614     }
   1615     for (ArtField& field : klass->GetIFields()) {
   1616       PrintField(os, &field, obj);
   1617     }
   1618   }
   1619 
   1620   bool InDumpSpace(const mirror::Object* object) {
   1621     return image_space_.Contains(object);
   1622   }
   1623 
   1624   const void* GetQuickOatCodeBegin(ArtMethod* m) SHARED_REQUIRES(Locks::mutator_lock_) {
   1625     const void* quick_code = m->GetEntryPointFromQuickCompiledCodePtrSize(
   1626         image_header_.GetPointerSize());
   1627     if (Runtime::Current()->GetClassLinker()->IsQuickResolutionStub(quick_code)) {
   1628       quick_code = oat_dumper_->GetQuickOatCode(m);
   1629     }
   1630     if (oat_dumper_->GetInstructionSet() == kThumb2) {
   1631       quick_code = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(quick_code) & ~0x1);
   1632     }
   1633     return quick_code;
   1634   }
   1635 
   1636   uint32_t GetQuickOatCodeSize(ArtMethod* m)
   1637       SHARED_REQUIRES(Locks::mutator_lock_) {
   1638     const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetQuickOatCodeBegin(m));
   1639     if (oat_code_begin == nullptr) {
   1640       return 0;
   1641     }
   1642     return oat_code_begin[-1];
   1643   }
   1644 
   1645   const void* GetQuickOatCodeEnd(ArtMethod* m)
   1646       SHARED_REQUIRES(Locks::mutator_lock_) {
   1647     const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetQuickOatCodeBegin(m));
   1648     if (oat_code_begin == nullptr) {
   1649       return nullptr;
   1650     }
   1651     return oat_code_begin + GetQuickOatCodeSize(m);
   1652   }
   1653 
   1654   static void Callback(mirror::Object* obj, void* arg) SHARED_REQUIRES(Locks::mutator_lock_) {
   1655     DCHECK(obj != nullptr);
   1656     DCHECK(arg != nullptr);
   1657     ImageDumper* state = reinterpret_cast<ImageDumper*>(arg);
   1658     if (!state->InDumpSpace(obj)) {
   1659       return;
   1660     }
   1661 
   1662     size_t object_bytes = obj->SizeOf();
   1663     size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
   1664     state->stats_.object_bytes += object_bytes;
   1665     state->stats_.alignment_bytes += alignment_bytes;
   1666 
   1667     std::ostream& os = state->vios_.Stream();
   1668 
   1669     mirror::Class* obj_class = obj->GetClass();
   1670     if (obj_class->IsArrayClass()) {
   1671       os << StringPrintf("%p: %s length:%d\n", obj, PrettyDescriptor(obj_class).c_str(),
   1672                          obj->AsArray()->GetLength());
   1673     } else if (obj->IsClass()) {
   1674       mirror::Class* klass = obj->AsClass();
   1675       os << StringPrintf("%p: java.lang.Class \"%s\" (", obj, PrettyDescriptor(klass).c_str())
   1676          << klass->GetStatus() << ")\n";
   1677     } else if (obj_class->IsStringClass()) {
   1678       os << StringPrintf("%p: java.lang.String %s\n", obj,
   1679                          PrintableString(obj->AsString()->ToModifiedUtf8().c_str()).c_str());
   1680     } else {
   1681       os << StringPrintf("%p: %s\n", obj, PrettyDescriptor(obj_class).c_str());
   1682     }
   1683     ScopedIndentation indent1(&state->vios_);
   1684     DumpFields(os, obj, obj_class);
   1685     const size_t image_pointer_size = state->image_header_.GetPointerSize();
   1686     if (obj->IsObjectArray()) {
   1687       auto* obj_array = obj->AsObjectArray<mirror::Object>();
   1688       for (int32_t i = 0, length = obj_array->GetLength(); i < length; i++) {
   1689         mirror::Object* value = obj_array->Get(i);
   1690         size_t run = 0;
   1691         for (int32_t j = i + 1; j < length; j++) {
   1692           if (value == obj_array->Get(j)) {
   1693             run++;
   1694           } else {
   1695             break;
   1696           }
   1697         }
   1698         if (run == 0) {
   1699           os << StringPrintf("%d: ", i);
   1700         } else {
   1701           os << StringPrintf("%d to %zd: ", i, i + run);
   1702           i = i + run;
   1703         }
   1704         mirror::Class* value_class =
   1705             (value == nullptr) ? obj_class->GetComponentType() : value->GetClass();
   1706         PrettyObjectValue(os, value_class, value);
   1707       }
   1708     } else if (obj->IsClass()) {
   1709       mirror::Class* klass = obj->AsClass();
   1710       if (klass->NumStaticFields() != 0) {
   1711         os << "STATICS:\n";
   1712         ScopedIndentation indent2(&state->vios_);
   1713         for (ArtField& field : klass->GetSFields()) {
   1714           PrintField(os, &field, field.GetDeclaringClass());
   1715         }
   1716       }
   1717     } else {
   1718       auto it = state->dex_caches_.find(obj);
   1719       if (it != state->dex_caches_.end()) {
   1720         auto* dex_cache = down_cast<mirror::DexCache*>(obj);
   1721         const auto& field_section = state->image_header_.GetImageSection(
   1722             ImageHeader::kSectionArtFields);
   1723         const auto& method_section = state->image_header_.GetMethodsSection();
   1724         size_t num_methods = dex_cache->NumResolvedMethods();
   1725         if (num_methods != 0u) {
   1726           os << "Methods (size=" << num_methods << "):";
   1727           ScopedIndentation indent2(&state->vios_);
   1728           auto* resolved_methods = dex_cache->GetResolvedMethods();
   1729           for (size_t i = 0, length = dex_cache->NumResolvedMethods(); i < length; ++i) {
   1730             auto* elem = mirror::DexCache::GetElementPtrSize(resolved_methods,
   1731                                                              i,
   1732                                                              image_pointer_size);
   1733             size_t run = 0;
   1734             for (size_t j = i + 1;
   1735                 j != length && elem == mirror::DexCache::GetElementPtrSize(resolved_methods,
   1736                                                                            j,
   1737                                                                            image_pointer_size);
   1738                 ++j, ++run) {}
   1739             if (run == 0) {
   1740               os << StringPrintf("%zd: ", i);
   1741             } else {
   1742               os << StringPrintf("%zd to %zd: ", i, i + run);
   1743               i = i + run;
   1744             }
   1745             std::string msg;
   1746             if (elem == nullptr) {
   1747               msg = "null";
   1748             } else if (method_section.Contains(
   1749                 reinterpret_cast<uint8_t*>(elem) - state->image_space_.Begin())) {
   1750               msg = PrettyMethod(reinterpret_cast<ArtMethod*>(elem));
   1751             } else {
   1752               msg = "<not in method section>";
   1753             }
   1754             os << StringPrintf("%p   %s\n", elem, msg.c_str());
   1755           }
   1756         }
   1757         size_t num_fields = dex_cache->NumResolvedFields();
   1758         if (num_fields != 0u) {
   1759           os << "Fields (size=" << num_fields << "):";
   1760           ScopedIndentation indent2(&state->vios_);
   1761           auto* resolved_fields = dex_cache->GetResolvedFields();
   1762           for (size_t i = 0, length = dex_cache->NumResolvedFields(); i < length; ++i) {
   1763             auto* elem = mirror::DexCache::GetElementPtrSize(resolved_fields, i, image_pointer_size);
   1764             size_t run = 0;
   1765             for (size_t j = i + 1;
   1766                 j != length && elem == mirror::DexCache::GetElementPtrSize(resolved_fields,
   1767                                                                            j,
   1768                                                                            image_pointer_size);
   1769                 ++j, ++run) {}
   1770             if (run == 0) {
   1771               os << StringPrintf("%zd: ", i);
   1772             } else {
   1773               os << StringPrintf("%zd to %zd: ", i, i + run);
   1774               i = i + run;
   1775             }
   1776             std::string msg;
   1777             if (elem == nullptr) {
   1778               msg = "null";
   1779             } else if (field_section.Contains(
   1780                 reinterpret_cast<uint8_t*>(elem) - state->image_space_.Begin())) {
   1781               msg = PrettyField(reinterpret_cast<ArtField*>(elem));
   1782             } else {
   1783               msg = "<not in field section>";
   1784             }
   1785             os << StringPrintf("%p   %s\n", elem, msg.c_str());
   1786           }
   1787         }
   1788       }
   1789     }
   1790     std::string temp;
   1791     state->stats_.Update(obj_class->GetDescriptor(&temp), object_bytes);
   1792   }
   1793 
   1794   void DumpMethod(ArtMethod* method, std::ostream& indent_os)
   1795       SHARED_REQUIRES(Locks::mutator_lock_) {
   1796     DCHECK(method != nullptr);
   1797     const void* quick_oat_code_begin = GetQuickOatCodeBegin(method);
   1798     const void* quick_oat_code_end = GetQuickOatCodeEnd(method);
   1799     const size_t pointer_size = image_header_.GetPointerSize();
   1800     OatQuickMethodHeader* method_header = reinterpret_cast<OatQuickMethodHeader*>(
   1801         reinterpret_cast<uintptr_t>(quick_oat_code_begin) - sizeof(OatQuickMethodHeader));
   1802     if (method->IsNative()) {
   1803       bool first_occurrence;
   1804       uint32_t quick_oat_code_size = GetQuickOatCodeSize(method);
   1805       ComputeOatSize(quick_oat_code_begin, &first_occurrence);
   1806       if (first_occurrence) {
   1807         stats_.native_to_managed_code_bytes += quick_oat_code_size;
   1808       }
   1809       if (quick_oat_code_begin != method->GetEntryPointFromQuickCompiledCodePtrSize(
   1810           image_header_.GetPointerSize())) {
   1811         indent_os << StringPrintf("OAT CODE: %p\n", quick_oat_code_begin);
   1812       }
   1813     } else if (method->IsAbstract() || method->IsClassInitializer()) {
   1814       // Don't print information for these.
   1815     } else if (method->IsRuntimeMethod()) {
   1816       ImtConflictTable* table = method->GetImtConflictTable(image_header_.GetPointerSize());
   1817       if (table != nullptr) {
   1818         indent_os << "IMT conflict table " << table << " method: ";
   1819         for (size_t i = 0, count = table->NumEntries(pointer_size); i < count; ++i) {
   1820           indent_os << PrettyMethod(table->GetImplementationMethod(i, pointer_size)) << " ";
   1821         }
   1822       }
   1823     } else {
   1824       const DexFile::CodeItem* code_item = method->GetCodeItem();
   1825       size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
   1826       stats_.dex_instruction_bytes += dex_instruction_bytes;
   1827 
   1828       bool first_occurrence;
   1829       size_t vmap_table_bytes = 0u;
   1830       if (!method_header->IsOptimized()) {
   1831         // Method compiled with the optimizing compiler have no vmap table.
   1832         vmap_table_bytes = ComputeOatSize(method_header->GetVmapTable(), &first_occurrence);
   1833         if (first_occurrence) {
   1834           stats_.vmap_table_bytes += vmap_table_bytes;
   1835         }
   1836       }
   1837 
   1838       uint32_t quick_oat_code_size = GetQuickOatCodeSize(method);
   1839       ComputeOatSize(quick_oat_code_begin, &first_occurrence);
   1840       if (first_occurrence) {
   1841         stats_.managed_code_bytes += quick_oat_code_size;
   1842         if (method->IsConstructor()) {
   1843           if (method->IsStatic()) {
   1844             stats_.class_initializer_code_bytes += quick_oat_code_size;
   1845           } else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
   1846             stats_.large_initializer_code_bytes += quick_oat_code_size;
   1847           }
   1848         } else if (dex_instruction_bytes > kLargeMethodDexBytes) {
   1849           stats_.large_method_code_bytes += quick_oat_code_size;
   1850         }
   1851       }
   1852       stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size;
   1853 
   1854       uint32_t method_access_flags = method->GetAccessFlags();
   1855 
   1856       indent_os << StringPrintf("OAT CODE: %p-%p\n", quick_oat_code_begin, quick_oat_code_end);
   1857       indent_os << StringPrintf("SIZE: Dex Instructions=%zd StackMaps=%zd AccessFlags=0x%x\n",
   1858                                 dex_instruction_bytes,
   1859                                 vmap_table_bytes,
   1860                                 method_access_flags);
   1861 
   1862       size_t total_size = dex_instruction_bytes +
   1863           vmap_table_bytes + quick_oat_code_size + ArtMethod::Size(image_header_.GetPointerSize());
   1864 
   1865       double expansion =
   1866       static_cast<double>(quick_oat_code_size) / static_cast<double>(dex_instruction_bytes);
   1867       stats_.ComputeOutliers(total_size, expansion, method);
   1868     }
   1869   }
   1870 
   1871   std::set<const void*> already_seen_;
   1872   // Compute the size of the given data within the oat file and whether this is the first time
   1873   // this data has been requested
   1874   size_t ComputeOatSize(const void* oat_data, bool* first_occurrence) {
   1875     if (already_seen_.count(oat_data) == 0) {
   1876       *first_occurrence = true;
   1877       already_seen_.insert(oat_data);
   1878     } else {
   1879       *first_occurrence = false;
   1880     }
   1881     return oat_dumper_->ComputeSize(oat_data);
   1882   }
   1883 
   1884  public:
   1885   struct Stats {
   1886     size_t oat_file_bytes;
   1887     size_t file_bytes;
   1888 
   1889     size_t header_bytes;
   1890     size_t object_bytes;
   1891     size_t art_field_bytes;
   1892     size_t art_method_bytes;
   1893     size_t dex_cache_arrays_bytes;
   1894     size_t interned_strings_bytes;
   1895     size_t class_table_bytes;
   1896     size_t bitmap_bytes;
   1897     size_t alignment_bytes;
   1898 
   1899     size_t managed_code_bytes;
   1900     size_t managed_code_bytes_ignoring_deduplication;
   1901     size_t managed_to_native_code_bytes;
   1902     size_t native_to_managed_code_bytes;
   1903     size_t class_initializer_code_bytes;
   1904     size_t large_initializer_code_bytes;
   1905     size_t large_method_code_bytes;
   1906 
   1907     size_t vmap_table_bytes;
   1908 
   1909     size_t dex_instruction_bytes;
   1910 
   1911     std::vector<ArtMethod*> method_outlier;
   1912     std::vector<size_t> method_outlier_size;
   1913     std::vector<double> method_outlier_expansion;
   1914     std::vector<std::pair<std::string, size_t>> oat_dex_file_sizes;
   1915 
   1916     Stats()
   1917         : oat_file_bytes(0),
   1918           file_bytes(0),
   1919           header_bytes(0),
   1920           object_bytes(0),
   1921           art_field_bytes(0),
   1922           art_method_bytes(0),
   1923           dex_cache_arrays_bytes(0),
   1924           interned_strings_bytes(0),
   1925           class_table_bytes(0),
   1926           bitmap_bytes(0),
   1927           alignment_bytes(0),
   1928           managed_code_bytes(0),
   1929           managed_code_bytes_ignoring_deduplication(0),
   1930           managed_to_native_code_bytes(0),
   1931           native_to_managed_code_bytes(0),
   1932           class_initializer_code_bytes(0),
   1933           large_initializer_code_bytes(0),
   1934           large_method_code_bytes(0),
   1935           vmap_table_bytes(0),
   1936           dex_instruction_bytes(0) {}
   1937 
   1938     struct SizeAndCount {
   1939       SizeAndCount(size_t bytes_in, size_t count_in) : bytes(bytes_in), count(count_in) {}
   1940       size_t bytes;
   1941       size_t count;
   1942     };
   1943     typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable;
   1944     SizeAndCountTable sizes_and_counts;
   1945 
   1946     void Update(const char* descriptor, size_t object_bytes_in) {
   1947       SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor);
   1948       if (it != sizes_and_counts.end()) {
   1949         it->second.bytes += object_bytes_in;
   1950         it->second.count += 1;
   1951       } else {
   1952         sizes_and_counts.Put(descriptor, SizeAndCount(object_bytes_in, 1));
   1953       }
   1954     }
   1955 
   1956     double PercentOfOatBytes(size_t size) {
   1957       return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100;
   1958     }
   1959 
   1960     double PercentOfFileBytes(size_t size) {
   1961       return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
   1962     }
   1963 
   1964     double PercentOfObjectBytes(size_t size) {
   1965       return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
   1966     }
   1967 
   1968     void ComputeOutliers(size_t total_size, double expansion, ArtMethod* method) {
   1969       method_outlier_size.push_back(total_size);
   1970       method_outlier_expansion.push_back(expansion);
   1971       method_outlier.push_back(method);
   1972     }
   1973 
   1974     void DumpOutliers(std::ostream& os)
   1975         SHARED_REQUIRES(Locks::mutator_lock_) {
   1976       size_t sum_of_sizes = 0;
   1977       size_t sum_of_sizes_squared = 0;
   1978       size_t sum_of_expansion = 0;
   1979       size_t sum_of_expansion_squared = 0;
   1980       size_t n = method_outlier_size.size();
   1981       if (n == 0) {
   1982         return;
   1983       }
   1984       for (size_t i = 0; i < n; i++) {
   1985         size_t cur_size = method_outlier_size[i];
   1986         sum_of_sizes += cur_size;
   1987         sum_of_sizes_squared += cur_size * cur_size;
   1988         double cur_expansion = method_outlier_expansion[i];
   1989         sum_of_expansion += cur_expansion;
   1990         sum_of_expansion_squared += cur_expansion * cur_expansion;
   1991       }
   1992       size_t size_mean = sum_of_sizes / n;
   1993       size_t size_variance = (sum_of_sizes_squared - sum_of_sizes * size_mean) / (n - 1);
   1994       double expansion_mean = sum_of_expansion / n;
   1995       double expansion_variance =
   1996           (sum_of_expansion_squared - sum_of_expansion * expansion_mean) / (n - 1);
   1997 
   1998       // Dump methods whose size is a certain number of standard deviations from the mean
   1999       size_t dumped_values = 0;
   2000       size_t skipped_values = 0;
   2001       for (size_t i = 100; i > 0; i--) {  // i is the current number of standard deviations
   2002         size_t cur_size_variance = i * i * size_variance;
   2003         bool first = true;
   2004         for (size_t j = 0; j < n; j++) {
   2005           size_t cur_size = method_outlier_size[j];
   2006           if (cur_size > size_mean) {
   2007             size_t cur_var = cur_size - size_mean;
   2008             cur_var = cur_var * cur_var;
   2009             if (cur_var > cur_size_variance) {
   2010               if (dumped_values > 20) {
   2011                 if (i == 1) {
   2012                   skipped_values++;
   2013                 } else {
   2014                   i = 2;  // jump to counting for 1 standard deviation
   2015                   break;
   2016                 }
   2017               } else {
   2018                 if (first) {
   2019                   os << "\nBig methods (size > " << i << " standard deviations the norm):\n";
   2020                   first = false;
   2021                 }
   2022                 os << PrettyMethod(method_outlier[j]) << " requires storage of "
   2023                     << PrettySize(cur_size) << "\n";
   2024                 method_outlier_size[j] = 0;  // don't consider this method again
   2025                 dumped_values++;
   2026               }
   2027             }
   2028           }
   2029         }
   2030       }
   2031       if (skipped_values > 0) {
   2032         os << "... skipped " << skipped_values
   2033            << " methods with size > 1 standard deviation from the norm\n";
   2034       }
   2035       os << std::flush;
   2036 
   2037       // Dump methods whose expansion is a certain number of standard deviations from the mean
   2038       dumped_values = 0;
   2039       skipped_values = 0;
   2040       for (size_t i = 10; i > 0; i--) {  // i is the current number of standard deviations
   2041         double cur_expansion_variance = i * i * expansion_variance;
   2042         bool first = true;
   2043         for (size_t j = 0; j < n; j++) {
   2044           double cur_expansion = method_outlier_expansion[j];
   2045           if (cur_expansion > expansion_mean) {
   2046             size_t cur_var = cur_expansion - expansion_mean;
   2047             cur_var = cur_var * cur_var;
   2048             if (cur_var > cur_expansion_variance) {
   2049               if (dumped_values > 20) {
   2050                 if (i == 1) {
   2051                   skipped_values++;
   2052                 } else {
   2053                   i = 2;  // jump to counting for 1 standard deviation
   2054                   break;
   2055                 }
   2056               } else {
   2057                 if (first) {
   2058                   os << "\nLarge expansion methods (size > " << i
   2059                       << " standard deviations the norm):\n";
   2060                   first = false;
   2061                 }
   2062                 os << PrettyMethod(method_outlier[j]) << " expanded code by "
   2063                    << cur_expansion << "\n";
   2064                 method_outlier_expansion[j] = 0.0;  // don't consider this method again
   2065                 dumped_values++;
   2066               }
   2067             }
   2068           }
   2069         }
   2070       }
   2071       if (skipped_values > 0) {
   2072         os << "... skipped " << skipped_values
   2073            << " methods with expansion > 1 standard deviation from the norm\n";
   2074       }
   2075       os << "\n" << std::flush;
   2076     }
   2077 
   2078     void Dump(std::ostream& os, std::ostream& indent_os)
   2079         SHARED_REQUIRES(Locks::mutator_lock_) {
   2080       {
   2081         os << "art_file_bytes = " << PrettySize(file_bytes) << "\n\n"
   2082            << "art_file_bytes = header_bytes + object_bytes + alignment_bytes\n";
   2083         indent_os << StringPrintf("header_bytes           =  %8zd (%2.0f%% of art file bytes)\n"
   2084                                   "object_bytes           =  %8zd (%2.0f%% of art file bytes)\n"
   2085                                   "art_field_bytes        =  %8zd (%2.0f%% of art file bytes)\n"
   2086                                   "art_method_bytes       =  %8zd (%2.0f%% of art file bytes)\n"
   2087                                   "dex_cache_arrays_bytes =  %8zd (%2.0f%% of art file bytes)\n"
   2088                                   "interned_string_bytes  =  %8zd (%2.0f%% of art file bytes)\n"
   2089                                   "class_table_bytes      =  %8zd (%2.0f%% of art file bytes)\n"
   2090                                   "bitmap_bytes           =  %8zd (%2.0f%% of art file bytes)\n"
   2091                                   "alignment_bytes        =  %8zd (%2.0f%% of art file bytes)\n\n",
   2092                                   header_bytes, PercentOfFileBytes(header_bytes),
   2093                                   object_bytes, PercentOfFileBytes(object_bytes),
   2094                                   art_field_bytes, PercentOfFileBytes(art_field_bytes),
   2095                                   art_method_bytes, PercentOfFileBytes(art_method_bytes),
   2096                                   dex_cache_arrays_bytes,
   2097                                   PercentOfFileBytes(dex_cache_arrays_bytes),
   2098                                   interned_strings_bytes,
   2099                                   PercentOfFileBytes(interned_strings_bytes),
   2100                                   class_table_bytes, PercentOfFileBytes(class_table_bytes),
   2101                                   bitmap_bytes, PercentOfFileBytes(bitmap_bytes),
   2102                                   alignment_bytes, PercentOfFileBytes(alignment_bytes))
   2103             << std::flush;
   2104         CHECK_EQ(file_bytes,
   2105                  header_bytes + object_bytes + art_field_bytes + art_method_bytes +
   2106                  dex_cache_arrays_bytes + interned_strings_bytes + class_table_bytes +
   2107                  bitmap_bytes + alignment_bytes);
   2108       }
   2109 
   2110       os << "object_bytes breakdown:\n";
   2111       size_t object_bytes_total = 0;
   2112       for (const auto& sizes_and_count : sizes_and_counts) {
   2113         const std::string& descriptor(sizes_and_count.first);
   2114         double average = static_cast<double>(sizes_and_count.second.bytes) /
   2115             static_cast<double>(sizes_and_count.second.count);
   2116         double percent = PercentOfObjectBytes(sizes_and_count.second.bytes);
   2117         os << StringPrintf("%32s %8zd bytes %6zd instances "
   2118                            "(%4.0f bytes/instance) %2.0f%% of object_bytes\n",
   2119                            descriptor.c_str(), sizes_and_count.second.bytes,
   2120                            sizes_and_count.second.count, average, percent);
   2121         object_bytes_total += sizes_and_count.second.bytes;
   2122       }
   2123       os << "\n" << std::flush;
   2124       CHECK_EQ(object_bytes, object_bytes_total);
   2125 
   2126       os << StringPrintf("oat_file_bytes               = %8zd\n"
   2127                          "managed_code_bytes           = %8zd (%2.0f%% of oat file bytes)\n"
   2128                          "managed_to_native_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
   2129                          "native_to_managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n\n"
   2130                          "class_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
   2131                          "large_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
   2132                          "large_method_code_bytes      = %8zd (%2.0f%% of oat file bytes)\n\n",
   2133                          oat_file_bytes,
   2134                          managed_code_bytes,
   2135                          PercentOfOatBytes(managed_code_bytes),
   2136                          managed_to_native_code_bytes,
   2137                          PercentOfOatBytes(managed_to_native_code_bytes),
   2138                          native_to_managed_code_bytes,
   2139                          PercentOfOatBytes(native_to_managed_code_bytes),
   2140                          class_initializer_code_bytes,
   2141                          PercentOfOatBytes(class_initializer_code_bytes),
   2142                          large_initializer_code_bytes,
   2143                          PercentOfOatBytes(large_initializer_code_bytes),
   2144                          large_method_code_bytes,
   2145                          PercentOfOatBytes(large_method_code_bytes))
   2146             << "DexFile sizes:\n";
   2147       for (const std::pair<std::string, size_t>& oat_dex_file_size : oat_dex_file_sizes) {
   2148         os << StringPrintf("%s = %zd (%2.0f%% of oat file bytes)\n",
   2149                            oat_dex_file_size.first.c_str(), oat_dex_file_size.second,
   2150                            PercentOfOatBytes(oat_dex_file_size.second));
   2151       }
   2152 
   2153       os << "\n" << StringPrintf("vmap_table_bytes       = %7zd (%2.0f%% of oat file bytes)\n\n",
   2154                                  vmap_table_bytes, PercentOfOatBytes(vmap_table_bytes))
   2155          << std::flush;
   2156 
   2157       os << StringPrintf("dex_instruction_bytes = %zd\n", dex_instruction_bytes)
   2158          << StringPrintf("managed_code_bytes expansion = %.2f (ignoring deduplication %.2f)\n\n",
   2159                          static_cast<double>(managed_code_bytes) /
   2160                              static_cast<double>(dex_instruction_bytes),
   2161                          static_cast<double>(managed_code_bytes_ignoring_deduplication) /
   2162                              static_cast<double>(dex_instruction_bytes))
   2163          << std::flush;
   2164 
   2165       DumpOutliers(os);
   2166     }
   2167   } stats_;
   2168 
   2169  private:
   2170   enum {
   2171     // Number of bytes for a constructor to be considered large. Based on the 1000 basic block
   2172     // threshold, we assume 2 bytes per instruction and 2 instructions per block.
   2173     kLargeConstructorDexBytes = 4000,
   2174     // Number of bytes for a method to be considered large. Based on the 4000 basic block
   2175     // threshold, we assume 2 bytes per instruction and 2 instructions per block.
   2176     kLargeMethodDexBytes = 16000
   2177   };
   2178 
   2179   // For performance, use the *os_ directly for anything that doesn't need indentation
   2180   // and prepare an indentation stream with default indentation 1.
   2181   std::ostream* os_;
   2182   VariableIndentationOutputStream vios_;
   2183   ScopedIndentation indent1_;
   2184 
   2185   gc::space::ImageSpace& image_space_;
   2186   const ImageHeader& image_header_;
   2187   std::unique_ptr<OatDumper> oat_dumper_;
   2188   OatDumperOptions* oat_dumper_options_;
   2189   std::set<mirror::Object*> dex_caches_;
   2190 
   2191   DISALLOW_COPY_AND_ASSIGN(ImageDumper);
   2192 };
   2193 
   2194 static int DumpImage(gc::space::ImageSpace* image_space,
   2195                      OatDumperOptions* options,
   2196                      std::ostream* os) SHARED_REQUIRES(Locks::mutator_lock_) {
   2197   const ImageHeader& image_header = image_space->GetImageHeader();
   2198   if (!image_header.IsValid()) {
   2199     fprintf(stderr, "Invalid image header %s\n", image_space->GetImageLocation().c_str());
   2200     return EXIT_FAILURE;
   2201   }
   2202   ImageDumper image_dumper(os, *image_space, image_header, options);
   2203   if (!image_dumper.Dump()) {
   2204     return EXIT_FAILURE;
   2205   }
   2206   return EXIT_SUCCESS;
   2207 }
   2208 
   2209 static int DumpImages(Runtime* runtime, OatDumperOptions* options, std::ostream* os) {
   2210   // Dumping the image, no explicit class loader.
   2211   ScopedNullHandle<mirror::ClassLoader> null_class_loader;
   2212   options->class_loader_ = &null_class_loader;
   2213 
   2214   ScopedObjectAccess soa(Thread::Current());
   2215   if (options->app_image_ != nullptr) {
   2216     if (options->app_oat_ == nullptr) {
   2217       LOG(ERROR) << "Can not dump app image without app oat file";
   2218       return EXIT_FAILURE;
   2219     }
   2220     // We can't know if the app image is 32 bits yet, but it contains pointers into the oat file.
   2221     // We need to map the oat file in the low 4gb or else the fixup wont be able to fit oat file
   2222     // pointers into 32 bit pointer sized ArtMethods.
   2223     std::string error_msg;
   2224     std::unique_ptr<OatFile> oat_file(OatFile::Open(options->app_oat_,
   2225                                                     options->app_oat_,
   2226                                                     nullptr,
   2227                                                     nullptr,
   2228                                                     false,
   2229                                                     /*low_4gb*/true,
   2230                                                     nullptr,
   2231                                                     &error_msg));
   2232     if (oat_file == nullptr) {
   2233       LOG(ERROR) << "Failed to open oat file " << options->app_oat_ << " with error " << error_msg;
   2234       return EXIT_FAILURE;
   2235     }
   2236     std::unique_ptr<gc::space::ImageSpace> space(
   2237         gc::space::ImageSpace::CreateFromAppImage(options->app_image_, oat_file.get(), &error_msg));
   2238     if (space == nullptr) {
   2239       LOG(ERROR) << "Failed to open app image " << options->app_image_ << " with error "
   2240                  << error_msg;
   2241     }
   2242     // Open dex files for the image.
   2243     std::vector<std::unique_ptr<const DexFile>> dex_files;
   2244     if (!runtime->GetClassLinker()->OpenImageDexFiles(space.get(), &dex_files, &error_msg)) {
   2245       LOG(ERROR) << "Failed to open app image dex files " << options->app_image_ << " with error "
   2246                  << error_msg;
   2247     }
   2248     // Dump the actual image.
   2249     int result = DumpImage(space.get(), options, os);
   2250     if (result != EXIT_SUCCESS) {
   2251       return result;
   2252     }
   2253     // Fall through to dump the boot images.
   2254   }
   2255 
   2256   gc::Heap* heap = runtime->GetHeap();
   2257   CHECK(heap->HasBootImageSpace()) << "No image spaces";
   2258   for (gc::space::ImageSpace* image_space : heap->GetBootImageSpaces()) {
   2259     int result = DumpImage(image_space, options, os);
   2260     if (result != EXIT_SUCCESS) {
   2261       return result;
   2262     }
   2263   }
   2264   return EXIT_SUCCESS;
   2265 }
   2266 
   2267 static int DumpOatWithRuntime(Runtime* runtime, OatFile* oat_file, OatDumperOptions* options,
   2268                               std::ostream* os) {
   2269   CHECK(runtime != nullptr && oat_file != nullptr && options != nullptr);
   2270 
   2271   Thread* self = Thread::Current();
   2272   CHECK(self != nullptr);
   2273   // Need well-known-classes.
   2274   WellKnownClasses::Init(self->GetJniEnv());
   2275 
   2276   // Need to register dex files to get a working dex cache.
   2277   ScopedObjectAccess soa(self);
   2278   ClassLinker* class_linker = runtime->GetClassLinker();
   2279   runtime->GetOatFileManager().RegisterOatFile(std::unique_ptr<const OatFile>(oat_file));
   2280   std::vector<const DexFile*> class_path;
   2281   for (const OatFile::OatDexFile* odf : oat_file->GetOatDexFiles()) {
   2282     std::string error_msg;
   2283     const DexFile* const dex_file = OpenDexFile(odf, &error_msg);
   2284     CHECK(dex_file != nullptr) << error_msg;
   2285     class_linker->RegisterDexFile(*dex_file, nullptr);
   2286     class_path.push_back(dex_file);
   2287   }
   2288 
   2289   // Need a class loader.
   2290   // Fake that we're a compiler.
   2291   jobject class_loader = class_linker->CreatePathClassLoader(self, class_path);
   2292 
   2293   // Use the class loader while dumping.
   2294   StackHandleScope<1> scope(self);
   2295   Handle<mirror::ClassLoader> loader_handle = scope.NewHandle(
   2296       soa.Decode<mirror::ClassLoader*>(class_loader));
   2297   options->class_loader_ = &loader_handle;
   2298 
   2299   OatDumper oat_dumper(*oat_file, *options);
   2300   bool success = oat_dumper.Dump(*os);
   2301   return (success) ? EXIT_SUCCESS : EXIT_FAILURE;
   2302 }
   2303 
   2304 static int DumpOatWithoutRuntime(OatFile* oat_file, OatDumperOptions* options, std::ostream* os) {
   2305   CHECK(oat_file != nullptr && options != nullptr);
   2306   // No image = no class loader.
   2307   ScopedNullHandle<mirror::ClassLoader> null_class_loader;
   2308   options->class_loader_ = &null_class_loader;
   2309 
   2310   OatDumper oat_dumper(*oat_file, *options);
   2311   bool success = oat_dumper.Dump(*os);
   2312   return (success) ? EXIT_SUCCESS : EXIT_FAILURE;
   2313 }
   2314 
   2315 static int DumpOat(Runtime* runtime, const char* oat_filename, OatDumperOptions* options,
   2316                    std::ostream* os) {
   2317   std::string error_msg;
   2318   OatFile* oat_file = OatFile::Open(oat_filename,
   2319                                     oat_filename,
   2320                                     nullptr,
   2321                                     nullptr,
   2322                                     false,
   2323                                     /*low_4gb*/false,
   2324                                     nullptr,
   2325                                     &error_msg);
   2326   if (oat_file == nullptr) {
   2327     fprintf(stderr, "Failed to open oat file from '%s': %s\n", oat_filename, error_msg.c_str());
   2328     return EXIT_FAILURE;
   2329   }
   2330 
   2331   if (runtime != nullptr) {
   2332     return DumpOatWithRuntime(runtime, oat_file, options, os);
   2333   } else {
   2334     return DumpOatWithoutRuntime(oat_file, options, os);
   2335   }
   2336 }
   2337 
   2338 static int SymbolizeOat(const char* oat_filename, std::string& output_name, bool no_bits) {
   2339   std::string error_msg;
   2340   OatFile* oat_file = OatFile::Open(oat_filename,
   2341                                     oat_filename,
   2342                                     nullptr,
   2343                                     nullptr,
   2344                                     false,
   2345                                     /*low_4gb*/false,
   2346                                     nullptr,
   2347                                     &error_msg);
   2348   if (oat_file == nullptr) {
   2349     fprintf(stderr, "Failed to open oat file from '%s': %s\n", oat_filename, error_msg.c_str());
   2350     return EXIT_FAILURE;
   2351   }
   2352 
   2353   bool result;
   2354   // Try to produce an ELF file of the same type. This is finicky, as we have used 32-bit ELF
   2355   // files for 64-bit code in the past.
   2356   if (Is64BitInstructionSet(oat_file->GetOatHeader().GetInstructionSet())) {
   2357     OatSymbolizer<ElfTypes64> oat_symbolizer(oat_file, output_name, no_bits);
   2358     result = oat_symbolizer.Symbolize();
   2359   } else {
   2360     OatSymbolizer<ElfTypes32> oat_symbolizer(oat_file, output_name, no_bits);
   2361     result = oat_symbolizer.Symbolize();
   2362   }
   2363   if (!result) {
   2364     fprintf(stderr, "Failed to symbolize\n");
   2365     return EXIT_FAILURE;
   2366   }
   2367 
   2368   return EXIT_SUCCESS;
   2369 }
   2370 
   2371 struct OatdumpArgs : public CmdlineArgs {
   2372  protected:
   2373   using Base = CmdlineArgs;
   2374 
   2375   virtual ParseStatus ParseCustom(const StringPiece& option,
   2376                                   std::string* error_msg) OVERRIDE {
   2377     {
   2378       ParseStatus base_parse = Base::ParseCustom(option, error_msg);
   2379       if (base_parse != kParseUnknownArgument) {
   2380         return base_parse;
   2381       }
   2382     }
   2383 
   2384     if (option.starts_with("--oat-file=")) {
   2385       oat_filename_ = option.substr(strlen("--oat-file=")).data();
   2386     } else if (option.starts_with("--image=")) {
   2387       image_location_ = option.substr(strlen("--image=")).data();
   2388     } else if (option == "--no-dump:vmap") {
   2389       dump_vmap_ = false;
   2390     } else if (option =="--dump:code_info_stack_maps") {
   2391       dump_code_info_stack_maps_ = true;
   2392     } else if (option == "--no-disassemble") {
   2393       disassemble_code_ = false;
   2394     } else if (option =="--header-only") {
   2395       dump_header_only_ = true;
   2396     } else if (option.starts_with("--symbolize=")) {
   2397       oat_filename_ = option.substr(strlen("--symbolize=")).data();
   2398       symbolize_ = true;
   2399     } else if (option.starts_with("--only-keep-debug")) {
   2400       only_keep_debug_ = true;
   2401     } else if (option.starts_with("--class-filter=")) {
   2402       class_filter_ = option.substr(strlen("--class-filter=")).data();
   2403     } else if (option.starts_with("--method-filter=")) {
   2404       method_filter_ = option.substr(strlen("--method-filter=")).data();
   2405     } else if (option.starts_with("--list-classes")) {
   2406       list_classes_ = true;
   2407     } else if (option.starts_with("--list-methods")) {
   2408       list_methods_ = true;
   2409     } else if (option.starts_with("--export-dex-to=")) {
   2410       export_dex_location_ = option.substr(strlen("--export-dex-to=")).data();
   2411     } else if (option.starts_with("--addr2instr=")) {
   2412       if (!ParseUint(option.substr(strlen("--addr2instr=")).data(), &addr2instr_)) {
   2413         *error_msg = "Address conversion failed";
   2414         return kParseError;
   2415       }
   2416     } else if (option.starts_with("--app-image=")) {
   2417       app_image_ = option.substr(strlen("--app-image=")).data();
   2418     } else if (option.starts_with("--app-oat=")) {
   2419       app_oat_ = option.substr(strlen("--app-oat=")).data();
   2420     } else {
   2421       return kParseUnknownArgument;
   2422     }
   2423 
   2424     return kParseOk;
   2425   }
   2426 
   2427   virtual ParseStatus ParseChecks(std::string* error_msg) OVERRIDE {
   2428     // Infer boot image location from the image location if possible.
   2429     if (boot_image_location_ == nullptr) {
   2430       boot_image_location_ = image_location_;
   2431     }
   2432 
   2433     // Perform the parent checks.
   2434     ParseStatus parent_checks = Base::ParseChecks(error_msg);
   2435     if (parent_checks != kParseOk) {
   2436       return parent_checks;
   2437     }
   2438 
   2439     // Perform our own checks.
   2440     if (image_location_ == nullptr && oat_filename_ == nullptr) {
   2441       *error_msg = "Either --image or --oat-file must be specified";
   2442       return kParseError;
   2443     } else if (image_location_ != nullptr && oat_filename_ != nullptr) {
   2444       *error_msg = "Either --image or --oat-file must be specified but not both";
   2445       return kParseError;
   2446     }
   2447 
   2448     return kParseOk;
   2449   }
   2450 
   2451   virtual std::string GetUsage() const {
   2452     std::string usage;
   2453 
   2454     usage +=
   2455         "Usage: oatdump [options] ...\n"
   2456         "    Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art\n"
   2457         "    Example: adb shell oatdump --image=/system/framework/boot.art\n"
   2458         "\n"
   2459         // Either oat-file or image is required.
   2460         "  --oat-file=<file.oat>: specifies an input oat filename.\n"
   2461         "      Example: --oat-file=/system/framework/boot.oat\n"
   2462         "\n"
   2463         "  --image=<file.art>: specifies an input image location.\n"
   2464         "      Example: --image=/system/framework/boot.art\n"
   2465         "\n"
   2466         "  --app-image=<file.art>: specifies an input app image. Must also have a specified\n"
   2467         " boot image and app oat file.\n"
   2468         "      Example: --app-image=app.art\n"
   2469         "\n"
   2470         "  --app-oat=<file.odex>: specifies an input app oat.\n"
   2471         "      Example: --app-oat=app.odex\n"
   2472         "\n";
   2473 
   2474     usage += Base::GetUsage();
   2475 
   2476     usage +=  // Optional.
   2477         "  --no-dump:vmap may be used to disable vmap dumping.\n"
   2478         "      Example: --no-dump:vmap\n"
   2479         "\n"
   2480         "  --dump:code_info_stack_maps enables dumping of stack maps in CodeInfo sections.\n"
   2481         "      Example: --dump:code_info_stack_maps\n"
   2482         "\n"
   2483         "  --no-disassemble may be used to disable disassembly.\n"
   2484         "      Example: --no-disassemble\n"
   2485         "\n"
   2486         "  --header-only may be used to print only the oat header.\n"
   2487         "      Example: --header-only\n"
   2488         "\n"
   2489         "  --list-classes may be used to list target file classes (can be used with filters).\n"
   2490         "      Example: --list-classes\n"
   2491         "      Example: --list-classes --class-filter=com.example.foo\n"
   2492         "\n"
   2493         "  --list-methods may be used to list target file methods (can be used with filters).\n"
   2494         "      Example: --list-methods\n"
   2495         "      Example: --list-methods --class-filter=com.example --method-filter=foo\n"
   2496         "\n"
   2497         "  --symbolize=<file.oat>: output a copy of file.oat with elf symbols included.\n"
   2498         "      Example: --symbolize=/system/framework/boot.oat\n"
   2499         "\n"
   2500         "  --only-keep-debug<file.oat>: Modifies the behaviour of --symbolize so that\n"
   2501         "      .rodata and .text sections are omitted in the output file to save space.\n"
   2502         "      Example: --symbolize=/system/framework/boot.oat --only-keep-debug\n"
   2503         "\n"
   2504         "  --class-filter=<class name>: only dumps classes that contain the filter.\n"
   2505         "      Example: --class-filter=com.example.foo\n"
   2506         "\n"
   2507         "  --method-filter=<method name>: only dumps methods that contain the filter.\n"
   2508         "      Example: --method-filter=foo\n"
   2509         "\n"
   2510         "  --export-dex-to=<directory>: may be used to export oat embedded dex files.\n"
   2511         "      Example: --export-dex-to=/data/local/tmp\n"
   2512         "\n"
   2513         "  --addr2instr=<address>: output matching method disassembled code from relative\n"
   2514         "                          address (e.g. PC from crash dump)\n"
   2515         "      Example: --addr2instr=0x00001a3b\n"
   2516         "\n";
   2517 
   2518     return usage;
   2519   }
   2520 
   2521  public:
   2522   const char* oat_filename_ = nullptr;
   2523   const char* class_filter_ = "";
   2524   const char* method_filter_ = "";
   2525   const char* image_location_ = nullptr;
   2526   std::string elf_filename_prefix_;
   2527   bool dump_vmap_ = true;
   2528   bool dump_code_info_stack_maps_ = false;
   2529   bool disassemble_code_ = true;
   2530   bool symbolize_ = false;
   2531   bool only_keep_debug_ = false;
   2532   bool list_classes_ = false;
   2533   bool list_methods_ = false;
   2534   bool dump_header_only_ = false;
   2535   uint32_t addr2instr_ = 0;
   2536   const char* export_dex_location_ = nullptr;
   2537   const char* app_image_ = nullptr;
   2538   const char* app_oat_ = nullptr;
   2539 };
   2540 
   2541 struct OatdumpMain : public CmdlineMain<OatdumpArgs> {
   2542   virtual bool NeedsRuntime() OVERRIDE {
   2543     CHECK(args_ != nullptr);
   2544 
   2545     // If we are only doing the oat file, disable absolute_addresses. Keep them for image dumping.
   2546     bool absolute_addresses = (args_->oat_filename_ == nullptr);
   2547 
   2548     oat_dumper_options_.reset(new OatDumperOptions(
   2549         args_->dump_vmap_,
   2550         args_->dump_code_info_stack_maps_,
   2551         args_->disassemble_code_,
   2552         absolute_addresses,
   2553         args_->class_filter_,
   2554         args_->method_filter_,
   2555         args_->list_classes_,
   2556         args_->list_methods_,
   2557         args_->dump_header_only_,
   2558         args_->export_dex_location_,
   2559         args_->app_image_,
   2560         args_->app_oat_,
   2561         args_->addr2instr_));
   2562 
   2563     return (args_->boot_image_location_ != nullptr || args_->image_location_ != nullptr) &&
   2564           !args_->symbolize_;
   2565   }
   2566 
   2567   virtual bool ExecuteWithoutRuntime() OVERRIDE {
   2568     CHECK(args_ != nullptr);
   2569     CHECK(args_->oat_filename_ != nullptr);
   2570 
   2571     MemMap::Init();
   2572 
   2573     if (args_->symbolize_) {
   2574       // ELF has special kind of section called SHT_NOBITS which allows us to create
   2575       // sections which exist but their data is omitted from the ELF file to save space.
   2576       // This is what "strip --only-keep-debug" does when it creates separate ELF file
   2577       // with only debug data. We use it in similar way to exclude .rodata and .text.
   2578       bool no_bits = args_->only_keep_debug_;
   2579       return SymbolizeOat(args_->oat_filename_, args_->output_name_, no_bits) == EXIT_SUCCESS;
   2580     } else {
   2581       return DumpOat(nullptr,
   2582                      args_->oat_filename_,
   2583                      oat_dumper_options_.get(),
   2584                      args_->os_) == EXIT_SUCCESS;
   2585     }
   2586   }
   2587 
   2588   virtual bool ExecuteWithRuntime(Runtime* runtime) {
   2589     CHECK(args_ != nullptr);
   2590 
   2591     if (args_->oat_filename_ != nullptr) {
   2592       return DumpOat(runtime,
   2593                      args_->oat_filename_,
   2594                      oat_dumper_options_.get(),
   2595                      args_->os_) == EXIT_SUCCESS;
   2596     }
   2597 
   2598     return DumpImages(runtime, oat_dumper_options_.get(), args_->os_) == EXIT_SUCCESS;
   2599   }
   2600 
   2601   std::unique_ptr<OatDumperOptions> oat_dumper_options_;
   2602 };
   2603 
   2604 }  // namespace art
   2605 
   2606 int main(int argc, char** argv) {
   2607   art::OatdumpMain main;
   2608   return main.Main(argc, argv);
   2609 }
   2610