/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <stdlib.h>

#include <fstream>
#include <iomanip>
#include <iostream>
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include "android-base/logging.h"
#include "android-base/parseint.h"
#include "android-base/stringprintf.h"
#include "android-base/strings.h"

#include "arch/instruction_set_features.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/bit_utils_iterator.h"
#include "base/indenter.h"
#include "base/os.h"
#include "base/safe_map.h"
#include "base/stats-inl.h"
#include "base/stl_util.h"
#include "base/unix_file/fd_file.h"
#include "class_linker-inl.h"
#include "class_linker.h"
#include "class_root-inl.h"
#include "compiled_method.h"
#include "debug/debug_info.h"
#include "debug/elf_debug_writer.h"
#include "debug/method_debug_info.h"
#include "dex/art_dex_file_loader.h"
#include "dex/class_accessor-inl.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_instruction-inl.h"
#include "dex/string_reference.h"
#include "dex/type_lookup_table.h"
#include "dexlayout.h"
#include "disassembler.h"
#include "elf/elf_builder.h"
#include "gc/accounting/space_bitmap-inl.h"
#include "gc/space/image_space.h"
#include "gc/space/large_object_space.h"
#include "gc/space/space-inl.h"
#include "image-inl.h"
#include "imtable-inl.h"
#include "index_bss_mapping.h"
#include "interpreter/unstarted_runtime.h"
#include "mirror/array-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "oat.h"
#include "oat_file-inl.h"
#include "oat_file_manager.h"
#include "scoped_thread_state_change-inl.h"
#include "stack.h"
#include "stack_map.h"
#include "stream/buffered_output_stream.h"
#include "stream/file_output_stream.h"
#include "subtype_check.h"
#include "thread_list.h"
#include "vdex_file.h"
#include "verifier/method_verifier.h"
#include "verifier/verifier_deps.h"
#include "well_known_classes.h"

#include <sys/stat.h>
#include "cmdline.h"

namespace art {

using android::base::StringPrintf;

const char* image_methods_descriptions_[] = {
  "kResolutionMethod",
  "kImtConflictMethod",
  "kImtUnimplementedMethod",
  "kSaveAllCalleeSavesMethod",
  "kSaveRefsOnlyMethod",
  "kSaveRefsAndArgsMethod",
  "kSaveEverythingMethod",
  "kSaveEverythingMethodForClinit",
  "kSaveEverythingMethodForSuspendCheck",
};

const char* image_roots_descriptions_[] = {
  "kDexCaches",
  "kClassRoots",
  "kSpecialRoots",
};

// Map is so that we don't allocate multiple dex files for the same OatDexFile.
static std::map<const OatDexFile*, std::unique_ptr<const DexFile>> opened_dex_files;

const DexFile* OpenDexFile(const OatDexFile* oat_dex_file, std::string* error_msg) {
  DCHECK(oat_dex_file != nullptr);
  auto it = opened_dex_files.find(oat_dex_file);
  if (it != opened_dex_files.end()) {
    return it->second.get();
  }
  const DexFile* ret = oat_dex_file->OpenDexFile(error_msg).release();
  opened_dex_files.emplace(oat_dex_file, std::unique_ptr<const DexFile>(ret));
  return ret;
}

template <typename ElfTypes>
class OatSymbolizer final {
 public:
  OatSymbolizer(const OatFile* oat_file, const std::string& output_name, bool no_bits) :
      oat_file_(oat_file),
      builder_(nullptr),
      output_name_(output_name.empty() ? "symbolized.oat" : output_name),
      no_bits_(no_bits) {
  }

  bool Symbolize() {
    const InstructionSet isa = oat_file_->GetOatHeader().GetInstructionSet();
    std::unique_ptr<const InstructionSetFeatures> features = InstructionSetFeatures::FromBitmap(
        isa, oat_file_->GetOatHeader().GetInstructionSetFeaturesBitmap());

    std::unique_ptr<File> elf_file(OS::CreateEmptyFile(output_name_.c_str()));
    if (elf_file == nullptr) {
      return false;
    }
    std::unique_ptr<BufferedOutputStream> output_stream =
        std::make_unique<BufferedOutputStream>(
            std::make_unique<FileOutputStream>(elf_file.get()));
    builder_.reset(new ElfBuilder<ElfTypes>(isa, output_stream.get()));

    builder_->Start();

    auto* rodata = builder_->GetRoData();
    auto* text = builder_->GetText();

    const uint8_t* rodata_begin = oat_file_->Begin();
    const size_t rodata_size = oat_file_->GetOatHeader().GetExecutableOffset();
    if (!no_bits_) {
      rodata->Start();
      rodata->WriteFully(rodata_begin, rodata_size);
      rodata->End();
    }

    const uint8_t* text_begin = oat_file_->Begin() + rodata_size;
    const size_t text_size = oat_file_->End() - text_begin;
    if (!no_bits_) {
      text->Start();
      text->WriteFully(text_begin, text_size);
      text->End();
    }

    builder_->PrepareDynamicSection(elf_file->GetPath(),
                                    rodata_size,
                                    text_size,
                                    oat_file_->DataBimgRelRoSize(),
                                    oat_file_->BssSize(),
                                    oat_file_->BssMethodsOffset(),
                                    oat_file_->BssRootsOffset(),
                                    oat_file_->VdexSize());
    builder_->WriteDynamicSection();

    const OatHeader& oat_header = oat_file_->GetOatHeader();
    #define DO_TRAMPOLINE(fn_name)                                                \
      if (oat_header.Get ## fn_name ## Offset() != 0) {                           \
        debug::MethodDebugInfo info = {};                                         \
        info.custom_name = #fn_name;                                              \
        info.isa = oat_header.GetInstructionSet();                                \
        info.is_code_address_text_relative = true;                                \
        size_t code_offset = oat_header.Get ## fn_name ## Offset();               \
        code_offset -= CompiledCode::CodeDelta(oat_header.GetInstructionSet());   \
        info.code_address = code_offset - oat_header.GetExecutableOffset();       \
        info.code_size = 0;  /* The symbol lasts until the next symbol. */        \
        method_debug_infos_.push_back(std::move(info));                           \
      }
    DO_TRAMPOLINE(JniDlsymLookupTrampoline);
    DO_TRAMPOLINE(JniDlsymLookupCriticalTrampoline);
    DO_TRAMPOLINE(QuickGenericJniTrampoline);
    DO_TRAMPOLINE(QuickImtConflictTrampoline);
    DO_TRAMPOLINE(QuickResolutionTrampoline);
    DO_TRAMPOLINE(QuickToInterpreterBridge);
    DO_TRAMPOLINE(NterpTrampoline);
    #undef DO_TRAMPOLINE

    Walk();

    // TODO: Try to symbolize link-time thunks?
    // This would require disassembling all methods to find branches outside the method code.

    // TODO: Add symbols for dex bytecode in the .dex section.

    debug::DebugInfo debug_info{};
    debug_info.compiled_methods = ArrayRef<const debug::MethodDebugInfo>(method_debug_infos_);

    debug::WriteDebugInfo(builder_.get(), debug_info);

    builder_->End();

    bool ret_value = builder_->Good();

    builder_.reset();
    output_stream.reset();

    if (elf_file->FlushCloseOrErase() != 0) {
      return false;
    }
    elf_file.reset();

    return ret_value;
  }

  void Walk() {
    std::vector<const OatDexFile*> oat_dex_files = oat_file_->GetOatDexFiles();
    for (size_t i = 0; i < oat_dex_files.size(); i++) {
      const OatDexFile* oat_dex_file = oat_dex_files[i];
      CHECK(oat_dex_file != nullptr);
      WalkOatDexFile(oat_dex_file);
    }
  }

  void WalkOatDexFile(const OatDexFile* oat_dex_file) {
    std::string error_msg;
    const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
    if (dex_file == nullptr) {
      return;
    }
    for (size_t class_def_index = 0;
        class_def_index < dex_file->NumClassDefs();
        class_def_index++) {
      const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
      OatClassType type = oat_class.GetType();
      switch (type) {
        case kOatClassAllCompiled:
        case kOatClassSomeCompiled:
          WalkOatClass(oat_class, *dex_file, class_def_index);
          break;

        case kOatClassNoneCompiled:
        case kOatClassMax:
          // Ignore.
          break;
      }
    }
  }

  void WalkOatClass(const OatFile::OatClass& oat_class,
                    const DexFile& dex_file,
                    uint32_t class_def_index) {
    ClassAccessor accessor(dex_file, class_def_index);
    // Note: even if this is an interface or a native class, we still have to walk it, as there
    //       might be a static initializer.
    uint32_t class_method_idx = 0;
    for (const ClassAccessor::Method& method : accessor.GetMethods()) {
      WalkOatMethod(oat_class.GetOatMethod(class_method_idx++),
                    dex_file,
                    class_def_index,
                    method.GetIndex(),
                    method.GetCodeItem(),
                    method.GetAccessFlags());
    }
  }

  void WalkOatMethod(const OatFile::OatMethod& oat_method,
                     const DexFile& dex_file,
                     uint32_t class_def_index,
                     uint32_t dex_method_index,
                     const dex::CodeItem* code_item,
                     uint32_t method_access_flags) {
    if ((method_access_flags & kAccAbstract) != 0) {
      // Abstract method, no code.
      return;
    }
    const OatHeader& oat_header = oat_file_->GetOatHeader();
    const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
    if (method_header == nullptr || method_header->GetCodeSize() == 0) {
      // No code.
      return;
    }

    uint32_t entry_point = oat_method.GetCodeOffset() - oat_header.GetExecutableOffset();
    // Clear Thumb2 bit.
    const void* code_address = EntryPointToCodePointer(reinterpret_cast<void*>(entry_point));

    debug::MethodDebugInfo info = {};
    DCHECK(info.custom_name.empty());
    info.dex_file = &dex_file;
    info.class_def_index = class_def_index;
    info.dex_method_index = dex_method_index;
    info.access_flags = method_access_flags;
    info.code_item = code_item;
    info.isa = oat_header.GetInstructionSet();
    info.deduped = !seen_offsets_.insert(oat_method.GetCodeOffset()).second;
    info.is_native_debuggable = oat_header.IsNativeDebuggable();
    info.is_optimized = method_header->IsOptimized();
    info.is_code_address_text_relative = true;
    info.code_address = reinterpret_cast<uintptr_t>(code_address);
    info.code_size = method_header->GetCodeSize();
    info.frame_size_in_bytes = method_header->GetFrameSizeInBytes();
    info.code_info = info.is_optimized ? method_header->GetOptimizedCodeInfoPtr() : nullptr;
    info.cfi = ArrayRef<uint8_t>();
    method_debug_infos_.push_back(info);
  }

 private:
  const OatFile* oat_file_;
  std::unique_ptr<ElfBuilder<ElfTypes>> builder_;
  std::vector<debug::MethodDebugInfo> method_debug_infos_;
  std::unordered_set<uint32_t> seen_offsets_;
  const std::string output_name_;
  bool no_bits_;
};

class OatDumperOptions {
 public:
  OatDumperOptions(bool dump_vmap,
                   bool dump_code_info_stack_maps,
                   bool disassemble_code,
                   bool absolute_addresses,
                   const char* class_filter,
                   const char* method_filter,
                   bool list_classes,
                   bool list_methods,
                   bool dump_header_only,
                   const char* export_dex_location,
                   const char* app_image,
                   const char* app_oat,
                   uint32_t addr2instr)
    : dump_vmap_(dump_vmap),
      dump_code_info_stack_maps_(dump_code_info_stack_maps),
      disassemble_code_(disassemble_code),
      absolute_addresses_(absolute_addresses),
      class_filter_(class_filter),
      method_filter_(method_filter),
      list_classes_(list_classes),
      list_methods_(list_methods),
      dump_header_only_(dump_header_only),
      export_dex_location_(export_dex_location),
      app_image_(app_image),
      app_oat_(app_oat),
      addr2instr_(addr2instr),
      class_loader_(nullptr) {}

  const bool dump_vmap_;
  const bool dump_code_info_stack_maps_;
  const bool disassemble_code_;
  const bool absolute_addresses_;
  const char* const class_filter_;
  const char* const method_filter_;
  const bool list_classes_;
  const bool list_methods_;
  const bool dump_header_only_;
  const char* const export_dex_location_;
  const char* const app_image_;
  const char* const app_oat_;
  uint32_t addr2instr_;
  Handle<mirror::ClassLoader>* class_loader_;
};

class OatDumper {
 public:
  OatDumper(const OatFile& oat_file, const OatDumperOptions& options)
    : oat_file_(oat_file),
      oat_dex_files_(oat_file.GetOatDexFiles()),
      options_(options),
      resolved_addr2instr_(0),
      instruction_set_(oat_file_.GetOatHeader().GetInstructionSet()),
      disassembler_(Disassembler::Create(instruction_set_,
                                         new DisassemblerOptions(
                                             options_.absolute_addresses_,
                                             oat_file.Begin(),
                                             oat_file.End(),
                                             /* can_read_literals_= */ true,
                                             Is64BitInstructionSet(instruction_set_)
                                                 ? &Thread::DumpThreadOffset<PointerSize::k64>
                                                 : &Thread::DumpThreadOffset<PointerSize::k32>))) {
    CHECK(options_.class_loader_ != nullptr);
    CHECK(options_.class_filter_ != nullptr);
    CHECK(options_.method_filter_ != nullptr);
    AddAllOffsets();
  }

  ~OatDumper() {
    delete disassembler_;
  }

  InstructionSet GetInstructionSet() {
    return instruction_set_;
  }

  using DexFileUniqV = std::vector<std::unique_ptr<const DexFile>>;

  bool Dump(std::ostream& os) {
    bool success = true;
    const OatHeader& oat_header = oat_file_.GetOatHeader();

    os << "MAGIC:\n";
    os << oat_header.GetMagic() << "\n\n";

    os << "LOCATION:\n";
    os << oat_file_.GetLocation() << "\n\n";

    os << "CHECKSUM:\n";
    os << StringPrintf("0x%08x\n\n", oat_header.GetChecksum());

    os << "INSTRUCTION SET:\n";
    os << oat_header.GetInstructionSet() << "\n\n";

    {
      std::unique_ptr<const InstructionSetFeatures> features(
          InstructionSetFeatures::FromBitmap(oat_header.GetInstructionSet(),
                                             oat_header.GetInstructionSetFeaturesBitmap()));
      os << "INSTRUCTION SET FEATURES:\n";
      os << features->GetFeatureString() << "\n\n";
    }

    os << "DEX FILE COUNT:\n";
    os << oat_header.GetDexFileCount() << "\n\n";

#define DUMP_OAT_HEADER_OFFSET(label, offset) \
    os << label " OFFSET:\n"; \
    os << StringPrintf("0x%08x", oat_header.offset()); \
    if (oat_header.offset() != 0 && options_.absolute_addresses_) { \
      os << StringPrintf(" (%p)", oat_file_.Begin() + oat_header.offset()); \
    } \
    os << StringPrintf("\n\n");

    DUMP_OAT_HEADER_OFFSET("EXECUTABLE", GetExecutableOffset);
    DUMP_OAT_HEADER_OFFSET("JNI DLSYM LOOKUP TRAMPOLINE",
                           GetJniDlsymLookupTrampolineOffset);
    DUMP_OAT_HEADER_OFFSET("JNI DLSYM LOOKUP CRITICAL TRAMPOLINE",
                           GetJniDlsymLookupCriticalTrampolineOffset);
    DUMP_OAT_HEADER_OFFSET("QUICK GENERIC JNI TRAMPOLINE",
                           GetQuickGenericJniTrampolineOffset);
    DUMP_OAT_HEADER_OFFSET("QUICK IMT CONFLICT TRAMPOLINE",
                           GetQuickImtConflictTrampolineOffset);
    DUMP_OAT_HEADER_OFFSET("QUICK RESOLUTION TRAMPOLINE",
                           GetQuickResolutionTrampolineOffset);
    DUMP_OAT_HEADER_OFFSET("QUICK TO INTERPRETER BRIDGE",
                           GetQuickToInterpreterBridgeOffset);
    DUMP_OAT_HEADER_OFFSET("NTERP_TRAMPOLINE",
                           GetNterpTrampolineOffset);
#undef DUMP_OAT_HEADER_OFFSET

    // Print the key-value store.
    {
      os << "KEY VALUE STORE:\n";
      size_t index = 0;
      const char* key;
      const char* value;
      while (oat_header.GetStoreKeyValuePairByIndex(index, &key, &value)) {
        os << key << " = " << value << "\n";
        index++;
      }
      os << "\n";
    }

    if (options_.absolute_addresses_) {
      os << "BEGIN:\n";
      os << reinterpret_cast<const void*>(oat_file_.Begin()) << "\n\n";

      os << "END:\n";
      os << reinterpret_cast<const void*>(oat_file_.End()) << "\n\n";
    }

    os << "SIZE:\n";
    os << oat_file_.Size() << "\n\n";

    os << std::flush;

    // If set, adjust relative address to be searched
    if (options_.addr2instr_ != 0) {
      resolved_addr2instr_ = options_.addr2instr_ + oat_header.GetExecutableOffset();
      os << "SEARCH ADDRESS (executable offset + input):\n";
      os << StringPrintf("0x%08x\n\n", resolved_addr2instr_);
    }

    // Dump .data.bimg.rel.ro entries.
    DumpDataBimgRelRoEntries(os);

    // Dump .bss summary, individual entries are dumped per dex file.
    os << ".bss: ";
    if (oat_file_.GetBssMethods().empty() && oat_file_.GetBssGcRoots().empty()) {
      os << "empty.\n\n";
    } else {
      os << oat_file_.GetBssMethods().size() << " methods, ";
      os << oat_file_.GetBssGcRoots().size() << " GC roots.\n\n";
    }

    // Dumping the dex file overview is compact enough to do even if header only.
    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
      const OatDexFile* oat_dex_file = oat_dex_files_[i];
      CHECK(oat_dex_file != nullptr);
      std::string error_msg;
      const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
      if (dex_file == nullptr) {
        os << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation() << "': "
           << error_msg;
        continue;
      }

      const DexLayoutSections* const layout_sections = oat_dex_file->GetDexLayoutSections();
      if (layout_sections != nullptr) {
        os << "Layout data\n";
        os << *layout_sections;
        os << "\n";
      }

      if (!options_.dump_header_only_) {
        // Dump .bss entries.
        DumpBssEntries(
            os,
            "ArtMethod",
            oat_dex_file->GetMethodBssMapping(),
            dex_file->NumMethodIds(),
            static_cast<size_t>(GetInstructionSetPointerSize(instruction_set_)),
            [=](uint32_t index) { return dex_file->PrettyMethod(index); });
        DumpBssEntries(
            os,
            "Class",
            oat_dex_file->GetTypeBssMapping(),
            dex_file->NumTypeIds(),
            sizeof(GcRoot<mirror::Class>),
            [=](uint32_t index) { return dex_file->PrettyType(dex::TypeIndex(index)); });
        DumpBssEntries(
            os,
            "Public Class",
            oat_dex_file->GetPublicTypeBssMapping(),
            dex_file->NumTypeIds(),
            sizeof(GcRoot<mirror::Class>),
            [=](uint32_t index) { return dex_file->PrettyType(dex::TypeIndex(index)); });
        DumpBssEntries(
            os,
            "Package Class",
            oat_dex_file->GetPackageTypeBssMapping(),
            dex_file->NumTypeIds(),
            sizeof(GcRoot<mirror::Class>),
            [=](uint32_t index) { return dex_file->PrettyType(dex::TypeIndex(index)); });
        DumpBssEntries(
            os,
            "String",
            oat_dex_file->GetStringBssMapping(),
            dex_file->NumStringIds(),
            sizeof(GcRoot<mirror::Class>),
            [=](uint32_t index) { return dex_file->StringDataByIdx(dex::StringIndex(index)); });
      }
    }

    if (!options_.dump_header_only_) {
      VariableIndentationOutputStream vios(&os);
      VdexFile::VdexFileHeader vdex_header = oat_file_.GetVdexFile()->GetVdexFileHeader();
      if (vdex_header.IsValid()) {
        std::string error_msg;
        std::vector<const DexFile*> dex_files;
        for (size_t i = 0; i < oat_dex_files_.size(); i++) {
          const DexFile* dex_file = OpenDexFile(oat_dex_files_[i], &error_msg);
          if (dex_file == nullptr) {
            os << "Error opening dex file: " << error_msg << std::endl;
            return false;
          }
          dex_files.push_back(dex_file);
        }
        verifier::VerifierDeps deps(dex_files, /*output_only=*/ false);
        if (!deps.ParseStoredData(dex_files, oat_file_.GetVdexFile()->GetVerifierDepsData())) {
          os << "Error parsing verifier dependencies." << std::endl;
          return false;
        }
        deps.Dump(&vios);
      } else {
        os << "UNRECOGNIZED vdex file, magic "
           << vdex_header.GetMagic()
           << ", version "
           << vdex_header.GetVdexVersion()
           << "\n";
      }
      for (size_t i = 0; i < oat_dex_files_.size(); i++) {
        const OatDexFile* oat_dex_file = oat_dex_files_[i];
        CHECK(oat_dex_file != nullptr);
        if (!DumpOatDexFile(os, *oat_dex_file)) {
          success = false;
        }
      }
    }

    if (options_.export_dex_location_) {
      std::string error_msg;
      std::string vdex_filename = GetVdexFilename(oat_file_.GetLocation());
      if (!OS::FileExists(vdex_filename.c_str())) {
        os << "File " << vdex_filename.c_str() << " does not exist\n";
        return false;
      }

      DexFileUniqV vdex_dex_files;
      std::unique_ptr<const VdexFile> vdex_file = OpenVdex(vdex_filename,
                                                           &vdex_dex_files,
                                                           &error_msg);
      if (vdex_file.get() == nullptr) {
        os << "Failed to open vdex file: " << error_msg << "\n";
        return false;
      }
      if (oat_dex_files_.size() != vdex_dex_files.size()) {
        os << "Dex files number in Vdex file does not match Dex files number in Oat file: "
           << vdex_dex_files.size() << " vs " << oat_dex_files_.size() << '\n';
        return false;
      }

      size_t i = 0;
      for (const auto& vdex_dex_file : vdex_dex_files) {
        const OatDexFile* oat_dex_file = oat_dex_files_[i];
        CHECK(oat_dex_file != nullptr);
        CHECK(vdex_dex_file != nullptr);

        // If a CompactDex file is detected within a Vdex container, DexLayout is used to convert
        // back to a StandardDex file. Since the converted DexFile will most likely not reproduce
        // the original input Dex file, the `update_checksum_` option is used to recompute the
        // checksum. If the vdex container does not contain cdex resources (`used_dexlayout` is
        // false), ExportDexFile() enforces a reproducible checksum verification.
        if (vdex_dex_file->IsCompactDexFile()) {
          Options options;
          options.compact_dex_level_ = CompactDexLevel::kCompactDexLevelNone;
          options.update_checksum_ = true;
          DexLayout dex_layout(options, /*info=*/ nullptr, /*out_file=*/ nullptr, /*header=*/ nullptr);
          std::unique_ptr<art::DexContainer> dex_container;
          bool result = dex_layout.ProcessDexFile(vdex_dex_file->GetLocation().c_str(),
                                                  vdex_dex_file.get(),
                                                  i,
                                                  &dex_container,
                                                  &error_msg);
          if (!result) {
            os << "DexLayout failed to process Dex file: " + error_msg;
            success = false;
            break;
          }
          DexContainer::Section* main_section = dex_container->GetMainSection();
          CHECK_EQ(dex_container->GetDataSection()->Size(), 0u);

          const ArtDexFileLoader dex_file_loader;
          std::unique_ptr<const DexFile> dex(dex_file_loader.Open(
              main_section->Begin(),
              main_section->Size(),
              vdex_dex_file->GetLocation(),
              vdex_file->GetLocationChecksum(i),
              /*oat_dex_file=*/ nullptr,
              /*verify=*/ false,
              /*verify_checksum=*/ true,
              &error_msg));
          if (dex == nullptr) {
            os << "Failed to load DexFile from layout container: " + error_msg;
            success = false;
            break;
          }
          if (dex->IsCompactDexFile()) {
            os <<"CompactDex conversion to StandardDex failed";
            success = false;
            break;
          }

          if (!ExportDexFile(os, *oat_dex_file, dex.get(), /*used_dexlayout=*/ true)) {
            success = false;
            break;
          }
        } else {
          if (!ExportDexFile(os, *oat_dex_file, vdex_dex_file.get(), /*used_dexlayout=*/ false)) {
            success = false;
            break;
          }
        }
        i++;
      }
    }

    {
      os << "OAT FILE STATS:\n";
      VariableIndentationOutputStream vios(&os);
      stats_.AddBytes(oat_file_.Size());
      stats_.DumpSizes(vios, "OatFile");
    }

    os << std::flush;
    return success;
  }

  size_t ComputeSize(const void* oat_data) {
    if (reinterpret_cast<const uint8_t*>(oat_data) < oat_file_.Begin() ||
        reinterpret_cast<const uint8_t*>(oat_data) > oat_file_.End()) {
      return 0;  // Address not in oat file
    }
    uintptr_t begin_offset = reinterpret_cast<uintptr_t>(oat_data) -
                             reinterpret_cast<uintptr_t>(oat_file_.Begin());
    auto it = offsets_.upper_bound(begin_offset);
    CHECK(it != offsets_.end());
    uintptr_t end_offset = *it;
    return end_offset - begin_offset;
  }

  InstructionSet GetOatInstructionSet() {
    return oat_file_.GetOatHeader().GetInstructionSet();
  }

  const void* GetQuickOatCode(ArtMethod* m) REQUIRES_SHARED(Locks::mutator_lock_) {
    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
      const OatDexFile* oat_dex_file = oat_dex_files_[i];
      CHECK(oat_dex_file != nullptr);
      std::string error_msg;
      const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
      if (dex_file == nullptr) {
        LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation()
            << "': " << error_msg;
      } else {
        const char* descriptor = m->GetDeclaringClassDescriptor();
        const dex::ClassDef* class_def =
            OatDexFile::FindClassDef(*dex_file, descriptor, ComputeModifiedUtf8Hash(descriptor));
        if (class_def != nullptr) {
          uint16_t class_def_index = dex_file->GetIndexForClassDef(*class_def);
          const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
          uint32_t oat_method_index;
          if (m->IsStatic() || m->IsDirect()) {
            // Simple case where the oat method index was stashed at load time.
            oat_method_index = m->GetMethodIndex();
          } else {
            // Compute the oat_method_index by search for its position in the class def.
            ClassAccessor accessor(*dex_file, *class_def);
            oat_method_index = accessor.NumDirectMethods();
            bool found_virtual = false;
            for (ClassAccessor::Method dex_method : accessor.GetVirtualMethods()) {
              // Check method index instead of identity in case of duplicate method definitions.
              if (dex_method.GetIndex() == m->GetDexMethodIndex()) {
                found_virtual = true;
                break;
              }
              ++oat_method_index;
            }
            CHECK(found_virtual) << "Didn't find oat method index for virtual method: "
                                 << dex_file->PrettyMethod(m->GetDexMethodIndex());
          }
          return oat_class.GetOatMethod(oat_method_index).GetQuickCode();
        }
      }
    }
    return nullptr;
  }

  // Returns nullptr and updates error_msg if the Vdex file cannot be opened, otherwise all Dex
  // files are stored in dex_files.
  std::unique_ptr<const VdexFile> OpenVdex(const std::string& vdex_filename,
                                           /* out */ DexFileUniqV* dex_files,
                                           /* out */ std::string* error_msg) {
    std::unique_ptr<const File> file(OS::OpenFileForReading(vdex_filename.c_str()));
    if (file == nullptr) {
      *error_msg = "Could not open file " + vdex_filename + " for reading.";
      return nullptr;
    }

    int64_t vdex_length = file->GetLength();
    if (vdex_length == -1) {
      *error_msg = "Could not read the length of file " + vdex_filename;
      return nullptr;
    }

    MemMap mmap = MemMap::MapFile(
        file->GetLength(),
        PROT_READ | PROT_WRITE,
        MAP_PRIVATE,
        file->Fd(),
        /* start offset= */ 0,
        /* low_4gb= */ false,
        vdex_filename.c_str(),
        error_msg);
    if (!mmap.IsValid()) {
      *error_msg = "Failed to mmap file " + vdex_filename + ": " + *error_msg;
      return nullptr;
    }

    std::unique_ptr<VdexFile> vdex_file(new VdexFile(std::move(mmap)));
    if (!vdex_file->IsValid()) {
      *error_msg = "Vdex file is not valid";
      return nullptr;
    }

    DexFileUniqV tmp_dex_files;
    if (!vdex_file->OpenAllDexFiles(&tmp_dex_files, error_msg)) {
      *error_msg = "Failed to open Dex files from Vdex: " + *error_msg;
      return nullptr;
    }

    *dex_files = std::move(tmp_dex_files);
    return vdex_file;
  }

  bool AddStatsObject(const void* address) {
    return seen_stats_objects_.insert(address).second;  // Inserted new entry.
  }

 private:
  void AddAllOffsets() {
    // We don't know the length of the code for each method, but we need to know where to stop
    // when disassembling. What we do know is that a region of code will be followed by some other
    // region, so if we keep a sorted sequence of the start of each region, we can infer the length
    // of a piece of code by using upper_bound to find the start of the next region.
    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
      const OatDexFile* oat_dex_file = oat_dex_files_[i];
      CHECK(oat_dex_file != nullptr);
      std::string error_msg;
      const DexFile* const dex_file = OpenDexFile(oat_dex_file, &error_msg);
      if (dex_file == nullptr) {
        LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation()
            << "': " << error_msg;
        continue;
      }
      offsets_.insert(reinterpret_cast<uintptr_t>(&dex_file->GetHeader()));
      for (ClassAccessor accessor : dex_file->GetClasses()) {
        const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(accessor.GetClassDefIndex());
        for (uint32_t class_method_index = 0;
            class_method_index < accessor.NumMethods();
            ++class_method_index) {
          AddOffsets(oat_class.GetOatMethod(class_method_index));
        }
      }
    }

    // If the last thing in the file is code for a method, there won't be an offset for the "next"
    // thing. Instead of having a special case in the upper_bound code, let's just add an entry
    // for the end of the file.
    offsets_.insert(oat_file_.Size());
  }

  static uint32_t AlignCodeOffset(uint32_t maybe_thumb_offset) {
    return maybe_thumb_offset & ~0x1;  // TODO: Make this Thumb2 specific.
  }

  void AddOffsets(const OatFile::OatMethod& oat_method) {
    uint32_t code_offset = oat_method.GetCodeOffset();
    if (oat_file_.GetOatHeader().GetInstructionSet() == InstructionSet::kThumb2) {
      code_offset &= ~0x1;
    }
    offsets_.insert(code_offset);
    offsets_.insert(oat_method.GetVmapTableOffset());
  }

  bool DumpOatDexFile(std::ostream& os, const OatDexFile& oat_dex_file) {
    bool success = true;
    bool stop_analysis = false;
    os << "OatDexFile:\n";
    os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str());
    os << StringPrintf("checksum: 0x%08x\n", oat_dex_file.GetDexFileLocationChecksum());

    const uint8_t* const oat_file_begin = oat_dex_file.GetOatFile()->Begin();
    if (oat_dex_file.GetOatFile()->ContainsDexCode()) {
      const uint8_t* const vdex_file_begin = oat_dex_file.GetOatFile()->DexBegin();

      // Print data range of the dex file embedded inside the corresponding vdex file.
      const uint8_t* const dex_file_pointer = oat_dex_file.GetDexFilePointer();
      uint32_t dex_offset = dchecked_integral_cast<uint32_t>(dex_file_pointer - vdex_file_begin);
      os << StringPrintf(
          "dex-file: 0x%08x..0x%08x\n",
          dex_offset,
          dchecked_integral_cast<uint32_t>(dex_offset + oat_dex_file.FileSize() - 1));
    } else {
      os << StringPrintf("dex-file not in VDEX file\n");
    }

    // Create the dex file early. A lot of print-out things depend on it.
    std::string error_msg;
    const DexFile* const dex_file = OpenDexFile(&oat_dex_file, &error_msg);
    if (dex_file == nullptr) {
      os << "NOT FOUND: " << error_msg << "\n\n";
      os << std::flush;
      return false;
    }

    // Print lookup table, if it exists.
    if (oat_dex_file.GetLookupTableData() != nullptr) {
      uint32_t table_offset = dchecked_integral_cast<uint32_t>(
          oat_dex_file.GetLookupTableData() - oat_file_begin);
      uint32_t table_size = TypeLookupTable::RawDataLength(dex_file->NumClassDefs());
      os << StringPrintf("type-table: 0x%08x..0x%08x\n",
                         table_offset,
                         table_offset + table_size - 1);
    }

    VariableIndentationOutputStream vios(&os);
    ScopedIndentation indent1(&vios);
    for (ClassAccessor accessor : dex_file->GetClasses()) {
      // TODO: Support regex
      const char* descriptor = accessor.GetDescriptor();
      if (DescriptorToDot(descriptor).find(options_.class_filter_) == std::string::npos) {
        continue;
      }

      const uint16_t class_def_index = accessor.GetClassDefIndex();
      uint32_t oat_class_offset = oat_dex_file.GetOatClassOffset(class_def_index);
      const OatFile::OatClass oat_class = oat_dex_file.GetOatClass(class_def_index);
      os << StringPrintf("%zd: %s (offset=0x%08x) (type_idx=%d)",
                         static_cast<ssize_t>(class_def_index),
                         descriptor,
                         oat_class_offset,
                         accessor.GetClassIdx().index_)
         << " (" << oat_class.GetStatus() << ")"
         << " (" << oat_class.GetType() << ")\n";
      // TODO: include bitmap here if type is kOatClassSomeCompiled?
      if (options_.list_classes_) {
        continue;
      }
      if (!DumpOatClass(&vios, oat_class, *dex_file, accessor, &stop_analysis)) {
        success = false;
      }
      if (stop_analysis) {
        os << std::flush;
        return success;
      }
    }
    os << "\n";
    os << std::flush;
    return success;
  }

  // Backwards compatible Dex file export. If dex_file is nullptr (valid Vdex file not present) the
  // Dex resource is extracted from the oat_dex_file and its checksum is repaired since it's not
  // unquickened. Otherwise the dex_file has been fully unquickened and is expected to verify the
  // original checksum.
  bool ExportDexFile(std::ostream& os,
                     const OatDexFile& oat_dex_file,
                     const DexFile* dex_file,
                     bool used_dexlayout) {
    std::string error_msg;
    std::string dex_file_location = oat_dex_file.GetDexFileLocation();

    // If dex_file (from unquicken or dexlayout) is not available, the output DexFile size is the
    // same as the one extracted from the Oat container (pre-oreo)
    size_t fsize = dex_file == nullptr ? oat_dex_file.FileSize() : dex_file->Size();

    // Some quick checks just in case
    if (fsize == 0 || fsize < sizeof(DexFile::Header)) {
      os << "Invalid dex file\n";
      return false;
    }

    if (dex_file == nullptr) {
      // Exported bytecode is quickened (dex-to-dex transformations present)
      dex_file = OpenDexFile(&oat_dex_file, &error_msg);
      if (dex_file == nullptr) {
        os << "Failed to open dex file '" << dex_file_location << "': " << error_msg;
        return false;
      }

      // Recompute checksum
      reinterpret_cast<DexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin()))->checksum_ =
          dex_file->CalculateChecksum();
    } else {
      // If dexlayout was used to convert CompactDex back to StandardDex, checksum will be updated
      // due to `update_checksum_` option, otherwise we expect a reproducible checksum.
      if (!used_dexlayout) {
        // Vdex unquicken output should match original input bytecode
        uint32_t orig_checksum =
            reinterpret_cast<DexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin()))->checksum_;
        if (orig_checksum != dex_file->CalculateChecksum()) {
          os << "Unexpected checksum from unquicken dex file '" << dex_file_location << "'\n";
          return false;
        }
      }
    }

    // Verify output directory exists
    if (!OS::DirectoryExists(options_.export_dex_location_)) {
      // TODO: Extend OS::DirectoryExists if symlink support is required
      os << options_.export_dex_location_ << " output directory not found or symlink\n";
      return false;
    }

    // Beautify path names
    if (dex_file_location.size() > PATH_MAX || dex_file_location.size() <= 0) {
      return false;
    }

    std::string dex_orig_name;
    size_t dex_orig_pos = dex_file_location.rfind('/');
    if (dex_orig_pos == std::string::npos)
      dex_orig_name = dex_file_location;
    else
      dex_orig_name = dex_file_location.substr(dex_orig_pos + 1);

    // A more elegant approach to efficiently name user installed apps is welcome
    if (dex_orig_name.size() == 8 &&
        dex_orig_name.compare("base.apk") == 0 &&
        dex_orig_pos != std::string::npos) {
      dex_file_location.erase(dex_orig_pos, strlen("base.apk") + 1);
      size_t apk_orig_pos = dex_file_location.rfind('/');
      if (apk_orig_pos != std::string::npos) {
        dex_orig_name = dex_file_location.substr(++apk_orig_pos);
      }
    }

    std::string out_dex_path(options_.export_dex_location_);
    if (out_dex_path.back() != '/') {
      out_dex_path.append("/");
    }
    out_dex_path.append(dex_orig_name);
    out_dex_path.append("_export.dex");
    if (out_dex_path.length() > PATH_MAX) {
      return false;
    }

    std::unique_ptr<File> file(OS::CreateEmptyFile(out_dex_path.c_str()));
    if (file.get() == nullptr) {
      os << "Failed to open output dex file " << out_dex_path;
      return false;
    }

    bool success = file->WriteFully(dex_file->Begin(), fsize);
    if (!success) {
      os << "Failed to write dex file";
      file->Erase();
      return false;
    }

    if (file->FlushCloseOrErase() != 0) {
      os << "Flush and close failed";
      return false;
    }

    os << StringPrintf("Dex file exported at %s (%zd bytes)\n", out_dex_path.c_str(), fsize);
    os << std::flush;

    return true;
  }

  bool DumpOatClass(VariableIndentationOutputStream* vios,
                    const OatFile::OatClass& oat_class,
                    const DexFile& dex_file,
                    const ClassAccessor& class_accessor,
                    bool* stop_analysis) {
    bool success = true;
    bool addr_found = false;
    uint32_t class_method_index = 0;
    for (const ClassAccessor::Method& method : class_accessor.GetMethods()) {
      if (!DumpOatMethod(vios,
                         dex_file.GetClassDef(class_accessor.GetClassDefIndex()),
                         class_method_index,
                         oat_class,
                         dex_file,
                         method.GetIndex(),
                         method.GetCodeItem(),
                         method.GetAccessFlags(),
                         &addr_found)) {
        success = false;
      }
      if (addr_found) {
        *stop_analysis = true;
        return success;
      }
      class_method_index++;
    }
    vios->Stream() << std::flush;
    return success;
  }

  static constexpr uint32_t kPrologueBytes = 16;

  // When this was picked, the largest arm method was 55,256 bytes and arm64 was 50,412 bytes.
  static constexpr uint32_t kMaxCodeSize = 100 * 1000;

  bool DumpOatMethod(VariableIndentationOutputStream* vios,
                     const dex::ClassDef& class_def,
                     uint32_t class_method_index,
                     const OatFile::OatClass& oat_class,
                     const DexFile& dex_file,
                     uint32_t dex_method_idx,
                     const dex::CodeItem* code_item,
                     uint32_t method_access_flags,
                     bool* addr_found) {
    bool success = true;

    CodeItemDataAccessor code_item_accessor(dex_file, code_item);

    // TODO: Support regex
    std::string method_name = dex_file.GetMethodName(dex_file.GetMethodId(dex_method_idx));
    if (method_name.find(options_.method_filter_) == std::string::npos) {
      return success;
    }

    std::string pretty_method = dex_file.PrettyMethod(dex_method_idx, true);
    vios->Stream() << StringPrintf("%d: %s (dex_method_idx=%d)\n",
                                   class_method_index, pretty_method.c_str(),
                                   dex_method_idx);
    if (options_.list_methods_) {
      return success;
    }

    uint32_t oat_method_offsets_offset = oat_class.GetOatMethodOffsetsOffset(class_method_index);
    const OatMethodOffsets* oat_method_offsets = oat_class.GetOatMethodOffsets(class_method_index);
    const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_index);
    uint32_t code_offset = oat_method.GetCodeOffset();
    uint32_t code_size = oat_method.GetQuickCodeSize();
    if (resolved_addr2instr_ != 0) {
      if (resolved_addr2instr_ > code_offset + code_size) {
        return success;
      } else {
        *addr_found = true;  // stop analyzing file at next iteration
      }
    }

    // Everything below is indented at least once.
    ScopedIndentation indent1(vios);

    {
      vios->Stream() << "DEX CODE:\n";
      ScopedIndentation indent2(vios);
      if (code_item_accessor.HasCodeItem()) {
        for (const DexInstructionPcPair& inst : code_item_accessor) {
          vios->Stream() << StringPrintf("0x%04x: ", inst.DexPc()) << inst->DumpHexLE(5)
                         << StringPrintf("\t| %s\n", inst->DumpString(&dex_file).c_str());
        }
      }
    }

    std::unique_ptr<StackHandleScope<1>> hs;
    std::unique_ptr<verifier::MethodVerifier> verifier;
    if (Runtime::Current() != nullptr) {
      // We need to have the handle scope stay live until after the verifier since the verifier has
      // a handle to the dex cache from hs.
      hs.reset(new StackHandleScope<1>(Thread::Current()));
      vios->Stream() << "VERIFIER TYPE ANALYSIS:\n";
      ScopedIndentation indent2(vios);
      verifier.reset(DumpVerifier(vios, hs.get(),
                                  dex_method_idx, &dex_file, class_def, code_item,
                                  method_access_flags));
    }
    {
      vios->Stream() << "OatMethodOffsets ";
      if (options_.absolute_addresses_) {
        vios->Stream() << StringPrintf("%p ", oat_method_offsets);
      }
      vios->Stream() << StringPrintf("(offset=0x%08x)\n", oat_method_offsets_offset);
      if (oat_method_offsets_offset > oat_file_.Size()) {
        vios->Stream() << StringPrintf(
            "WARNING: oat method offsets offset 0x%08x is past end of file 0x%08zx.\n",
            oat_method_offsets_offset, oat_file_.Size());
        // If we can't read OatMethodOffsets, the rest of the data is dangerous to read.
        vios->Stream() << std::flush;
        return false;
      }

      ScopedIndentation indent2(vios);
      vios->Stream() << StringPrintf("code_offset: 0x%08x ", code_offset);
      uint32_t aligned_code_begin = AlignCodeOffset(oat_method.GetCodeOffset());
      if (aligned_code_begin > oat_file_.Size()) {
        vios->Stream() << StringPrintf("WARNING: "
                                       "code offset 0x%08x is past end of file 0x%08zx.\n",
                                       aligned_code_begin, oat_file_.Size());
        success = false;
      }
      vios->Stream() << "\n";
    }
    {
      vios->Stream() << "OatQuickMethodHeader ";
      uint32_t method_header_offset = oat_method.GetOatQuickMethodHeaderOffset();
      const OatQuickMethodHeader* method_header = oat_method.GetOatQuickMethodHeader();
      if (AddStatsObject(method_header)) {
        stats_["QuickMethodHeader"].AddBytes(sizeof(*method_header));
      }
      if (options_.absolute_addresses_) {
        vios->Stream() << StringPrintf("%p ", method_header);
      }
      vios->Stream() << StringPrintf("(offset=0x%08x)\n", method_header_offset);
      if (method_header_offset > oat_file_.Size() ||
          sizeof(OatQuickMethodHeader) > oat_file_.Size() - method_header_offset) {
        vios->Stream() << StringPrintf(
            "WARNING: oat quick method header at offset 0x%08x is past end of file 0x%08zx.\n",
            method_header_offset, oat_file_.Size());
        // If we can't read the OatQuickMethodHeader, the rest of the data is dangerous to read.
        vios->Stream() << std::flush;
        return false;
      }

      ScopedIndentation indent2(vios);
      vios->Stream() << "vmap_table: ";
      if (options_.absolute_addresses_) {
        vios->Stream() << StringPrintf("%p ", oat_method.GetVmapTable());
      }
      uint32_t vmap_table_offset =
          (method_header == nullptr) ? 0 : method_header->GetCodeInfoOffset();
      vios->Stream() << StringPrintf("(offset=0x%08x)\n", vmap_table_offset);

      size_t vmap_table_offset_limit =
          IsMethodGeneratedByDexToDexCompiler(oat_method, code_item_accessor)
              ? oat_file_.GetVdexFile()->Size()
              : method_header->GetCode() - oat_file_.Begin();
      if (vmap_table_offset >= vmap_table_offset_limit) {
        vios->Stream() << StringPrintf("WARNING: "
                                       "vmap table offset 0x%08x is past end of file 0x%08zx. ",
                                       vmap_table_offset,
                                       vmap_table_offset_limit);
        success = false;
      } else if (options_.dump_vmap_) {
        DumpVmapData(vios, oat_method, code_item_accessor);
      }
    }
    {
      vios->Stream() << "QuickMethodFrameInfo\n";

      ScopedIndentation indent2(vios);
      vios->Stream()
          << StringPrintf("frame_size_in_bytes: %zd\n", oat_method.GetFrameSizeInBytes());
      vios->Stream() << StringPrintf("core_spill_mask: 0x%08x ", oat_method.GetCoreSpillMask());
      DumpSpillMask(vios->Stream(), oat_method.GetCoreSpillMask(), false);
      vios->Stream() << "\n";
      vios->Stream() << StringPrintf("fp_spill_mask: 0x%08x ", oat_method.GetFpSpillMask());
      DumpSpillMask(vios->Stream(), oat_method.GetFpSpillMask(), true);
      vios->Stream() << "\n";
    }
    {
      // Based on spill masks from QuickMethodFrameInfo so placed
      // after it is dumped, but useful for understanding quick
      // code, so dumped here.
      ScopedIndentation indent2(vios);
      DumpVregLocations(vios->Stream(), oat_method, code_item_accessor);
    }
    {
      vios->Stream() << "CODE: ";
      {
        const void* code = oat_method.GetQuickCode();
        uint32_t aligned_code_begin = AlignCodeOffset(code_offset);
        uint64_t aligned_code_end = aligned_code_begin + code_size;
        if (AddStatsObject(code)) {
          stats_["Code"].AddBytes(code_size);
        }

        if (options_.absolute_addresses_) {
          vios->Stream() << StringPrintf("%p ", code);
        }
        vios->Stream() << StringPrintf("(code_offset=0x%08x size=%u)%s\n",
                                       code_offset,
                                       code_size,
                                       code != nullptr ? "..." : "");

        ScopedIndentation indent2(vios);
        if (aligned_code_begin > oat_file_.Size()) {
          vios->Stream() << StringPrintf("WARNING: "
                                         "start of code at 0x%08x is past end of file 0x%08zx.",
                                         aligned_code_begin, oat_file_.Size());
          success = false;
        } else if (aligned_code_end > oat_file_.Size()) {
          vios->Stream() << StringPrintf(
              "WARNING: "
              "end of code at 0x%08" PRIx64 " is past end of file 0x%08zx. "
              "code size is 0x%08x.\n",
              aligned_code_end,
              oat_file_.Size(),
              code_size);
          success = false;
          if (options_.disassemble_code_) {
            if (aligned_code_begin + kPrologueBytes <= oat_file_.Size()) {
              DumpCode(vios, oat_method, code_item_accessor, true, kPrologueBytes);
            }
          }
        } else if (code_size > kMaxCodeSize) {
          vios->Stream() << StringPrintf(
              "WARNING: "
              "code size %d is bigger than max expected threshold of %d. "
              "code size is 0x%08x.\n",
              code_size,
              kMaxCodeSize,
              code_size);
          success = false;
          if (options_.disassemble_code_) {
            if (aligned_code_begin + kPrologueBytes <= oat_file_.Size()) {
              DumpCode(vios, oat_method, code_item_accessor, true, kPrologueBytes);
            }
          }
        } else if (options_.disassemble_code_) {
          DumpCode(vios, oat_method, code_item_accessor, !success, 0);
        }
      }
    }
    vios->Stream() << std::flush;
    return success;
  }

  void DumpSpillMask(std::ostream& os, uint32_t spill_mask, bool is_float) {
    if (spill_mask == 0) {
      return;
    }
    os << "(";
    for (size_t i = 0; i < 32; i++) {
      if ((spill_mask & (1 << i)) != 0) {
        if (is_float) {
          os << "fr" << i;
        } else {
          os << "r" << i;
        }
        spill_mask ^= 1 << i;  // clear bit
        if (spill_mask != 0) {
          os << ", ";
        } else {
          break;
        }
      }
    }
    os << ")";
  }

  // Display data stored at the the vmap offset of an oat method.
  void DumpVmapData(VariableIndentationOutputStream* vios,
                    const OatFile::OatMethod& oat_method,
                    const CodeItemDataAccessor& code_item_accessor) {
    if (IsMethodGeneratedByOptimizingCompiler(oat_method, code_item_accessor)) {
      // The optimizing compiler outputs its CodeInfo data in the vmap table.
      const uint8_t* raw_code_info = oat_method.GetVmapTable();
      if (raw_code_info != nullptr) {
        CodeInfo code_info(raw_code_info);
        DCHECK(code_item_accessor.HasCodeItem());
        ScopedIndentation indent1(vios);
        DumpCodeInfo(vios, code_info, oat_method);
      }
    } else if (IsMethodGeneratedByDexToDexCompiler(oat_method, code_item_accessor)) {
      // We don't encode the size in the table, so just emit that we have quickened
      // information.
      ScopedIndentation indent(vios);
      vios->Stream() << "quickened data\n";
    } else {
      // Otherwise, there is nothing to display.
    }
  }

  // Display a CodeInfo object emitted by the optimizing compiler.
  void DumpCodeInfo(VariableIndentationOutputStream* vios,
                    const CodeInfo& code_info,
                    const OatFile::OatMethod& oat_method) {
    code_info.Dump(vios,
                   oat_method.GetCodeOffset(),
                   options_.dump_code_info_stack_maps_,
                   instruction_set_);
  }

  static int GetOutVROffset(uint16_t out_num, InstructionSet isa) {
    // According to stack model, the first out is above the Method referernce.
    return static_cast<size_t>(InstructionSetPointerSize(isa)) + out_num * sizeof(uint32_t);
  }

  static uint32_t GetVRegOffsetFromQuickCode(const CodeItemDataAccessor& code_item_accessor,
                                             uint32_t core_spills,
                                             uint32_t fp_spills,
                                             size_t frame_size,
                                             int reg,
                                             InstructionSet isa) {
    PointerSize pointer_size = InstructionSetPointerSize(isa);
    if (kIsDebugBuild) {
      auto* runtime = Runtime::Current();
      if (runtime != nullptr) {
        CHECK_EQ(runtime->GetClassLinker()->GetImagePointerSize(), pointer_size);
      }
    }
    DCHECK_ALIGNED(frame_size, kStackAlignment);
    DCHECK_NE(reg, -1);
    int spill_size = POPCOUNT(core_spills) * GetBytesPerGprSpillLocation(isa)
        + POPCOUNT(fp_spills) * GetBytesPerFprSpillLocation(isa)
        + sizeof(uint32_t);  // Filler.
    int num_regs = code_item_accessor.RegistersSize() - code_item_accessor.InsSize();
    int temp_threshold = code_item_accessor.RegistersSize();
    const int max_num_special_temps = 1;
    if (reg == temp_threshold) {
      // The current method pointer corresponds to special location on stack.
      return 0;
    } else if (reg >= temp_threshold + max_num_special_temps) {
      /*
       * Special temporaries may have custom locations and the logic above deals with that.
       * However, non-special temporaries are placed relative to the outs.
       */
      int temps_start = code_item_accessor.OutsSize() * sizeof(uint32_t)
          + static_cast<size_t>(pointer_size) /* art method */;
      int relative_offset = (reg - (temp_threshold + max_num_special_temps)) * sizeof(uint32_t);
      return temps_start + relative_offset;
    } else if (reg < num_regs) {
      int locals_start = frame_size - spill_size - num_regs * sizeof(uint32_t);
      return locals_start + (reg * sizeof(uint32_t));
    } else {
      // Handle ins.
      return frame_size + ((reg - num_regs) * sizeof(uint32_t))
          + static_cast<size_t>(pointer_size) /* art method */;
    }
  }

  void DumpVregLocations(std::ostream& os, const OatFile::OatMethod& oat_method,
                         const CodeItemDataAccessor& code_item_accessor) {
    if (code_item_accessor.HasCodeItem()) {
      size_t num_locals_ins = code_item_accessor.RegistersSize();
      size_t num_ins = code_item_accessor.InsSize();
      size_t num_locals = num_locals_ins - num_ins;
      size_t num_outs = code_item_accessor.OutsSize();

      os << "vr_stack_locations:";
      for (size_t reg = 0; reg <= num_locals_ins; reg++) {
        // For readability, delimit the different kinds of VRs.
        if (reg == num_locals_ins) {
          os << "\n\tmethod*:";
        } else if (reg == num_locals && num_ins > 0) {
          os << "\n\tins:";
        } else if (reg == 0 && num_locals > 0) {
          os << "\n\tlocals:";
        }

        uint32_t offset = GetVRegOffsetFromQuickCode(code_item_accessor,
                                                     oat_method.GetCoreSpillMask(),
                                                     oat_method.GetFpSpillMask(),
                                                     oat_method.GetFrameSizeInBytes(),
                                                     reg,
                                                     GetInstructionSet());
        os << " v" << reg << "[sp + #" << offset << "]";
      }

      for (size_t out_reg = 0; out_reg < num_outs; out_reg++) {
        if (out_reg == 0) {
          os << "\n\touts:";
        }

        uint32_t offset = GetOutVROffset(out_reg, GetInstructionSet());
        os << " v" << out_reg << "[sp + #" << offset << "]";
      }

      os << "\n";
    }
  }

  // Has `oat_method` -- corresponding to the Dex `code_item` -- been compiled by
  // the optimizing compiler?
  static bool IsMethodGeneratedByOptimizingCompiler(
      const OatFile::OatMethod& oat_method,
      const CodeItemDataAccessor& code_item_accessor) {
    // If the native GC map is null and the Dex `code_item` is not
    // null, then this method has been compiled with the optimizing
    // compiler.
    return oat_method.GetQuickCode() != nullptr &&
           oat_method.GetVmapTable() != nullptr &&
           code_item_accessor.HasCodeItem();
  }

  // Has `oat_method` -- corresponding to the Dex `code_item` -- been compiled by
  // the dextodex compiler?
  static bool IsMethodGeneratedByDexToDexCompiler(
      const OatFile::OatMethod& oat_method,
      const CodeItemDataAccessor& code_item_accessor) {
    // If the quick code is null, the Dex `code_item` is not
    // null, and the vmap table is not null, then this method has been compiled
    // with the dextodex compiler.
    return oat_method.GetQuickCode() == nullptr &&
           oat_method.GetVmapTable() != nullptr &&
           code_item_accessor.HasCodeItem();
  }

  verifier::MethodVerifier* DumpVerifier(VariableIndentationOutputStream* vios,
                                         StackHandleScope<1>* hs,
                                         uint32_t dex_method_idx,
                                         const DexFile* dex_file,
                                         const dex::ClassDef& class_def,
                                         const dex::CodeItem* code_item,
                                         uint32_t method_access_flags) {
    if ((method_access_flags & kAccNative) == 0) {
      ScopedObjectAccess soa(Thread::Current());
      Runtime* const runtime = Runtime::Current();
      DCHECK(options_.class_loader_ != nullptr);
      Handle<mirror::DexCache> dex_cache = hs->NewHandle(
          runtime->GetClassLinker()->RegisterDexFile(*dex_file, options_.class_loader_->Get()));
      CHECK(dex_cache != nullptr);
      ArtMethod* method = runtime->GetClassLinker()->ResolveMethodWithoutInvokeType(
          dex_method_idx, dex_cache, *options_.class_loader_);
      if (method == nullptr) {
        soa.Self()->ClearException();
        return nullptr;
      }
      return verifier::MethodVerifier::VerifyMethodAndDump(
          soa.Self(), vios, dex_method_idx, dex_file, dex_cache, *options_.class_loader_,
          class_def, code_item, method, method_access_flags, /* api_level= */ 0);
    }

    return nullptr;
  }

  void DumpCode(VariableIndentationOutputStream* vios,
                const OatFile::OatMethod& oat_method,
                const CodeItemDataAccessor& code_item_accessor,
                bool bad_input, size_t code_size) {
    const void* quick_code = oat_method.GetQuickCode();

    if (code_size == 0) {
      code_size = oat_method.GetQuickCodeSize();
    }
    if (code_size == 0 || quick_code == nullptr) {
      vios->Stream() << "NO CODE!\n";
      return;
    } else if (!bad_input && IsMethodGeneratedByOptimizingCompiler(oat_method,
                                                                   code_item_accessor)) {
      // The optimizing compiler outputs its CodeInfo data in the vmap table.
      CodeInfo code_info(oat_method.GetVmapTable());
      if (AddStatsObject(oat_method.GetVmapTable())) {
        code_info.CollectSizeStats(oat_method.GetVmapTable(), stats_["CodeInfo"]);
      }
      std::unordered_map<uint32_t, std::vector<StackMap>> stack_maps;
      for (const StackMap& it : code_info.GetStackMaps()) {
        stack_maps[it.GetNativePcOffset(instruction_set_)].push_back(it);
      }

      const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
      size_t offset = 0;
      while (offset < code_size) {
        offset += disassembler_->Dump(vios->Stream(), quick_native_pc + offset);
        auto it = stack_maps.find(offset);
        if (it != stack_maps.end()) {
          ScopedIndentation indent1(vios);
          for (StackMap stack_map : it->second) {
            stack_map.Dump(vios, code_info, oat_method.GetCodeOffset(), instruction_set_);
          }
          stack_maps.erase(it);
        }
      }
      DCHECK_EQ(stack_maps.size(), 0u);  // Check that all stack maps have been printed.
    } else {
      const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
      size_t offset = 0;
      while (offset < code_size) {
        offset += disassembler_->Dump(vios->Stream(), quick_native_pc + offset);
      }
    }
  }

  std::pair<const uint8_t*, const uint8_t*> GetBootImageLiveObjectsDataRange(gc::Heap* heap) const
      REQUIRES_SHARED(Locks::mutator_lock_) {
    const std::vector<gc::space::ImageSpace*>& boot_image_spaces = heap->GetBootImageSpaces();
    const ImageHeader& main_header = boot_image_spaces[0]->GetImageHeader();
    ObjPtr<mirror::ObjectArray<mirror::Object>> boot_image_live_objects =
        ObjPtr<mirror::ObjectArray<mirror::Object>>::DownCast(
            main_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kBootImageLiveObjects));
    DCHECK(boot_image_live_objects != nullptr);
    DCHECK(heap->ObjectIsInBootImageSpace(boot_image_live_objects));
    const uint8_t* boot_image_live_objects_address =
        reinterpret_cast<const uint8_t*>(boot_image_live_objects.Ptr());
    uint32_t begin_offset = mirror::ObjectArray<mirror::Object>::OffsetOfElement(0).Uint32Value();
    uint32_t end_offset = mirror::ObjectArray<mirror::Object>::OffsetOfElement(
        boot_image_live_objects->GetLength()).Uint32Value();
    return std::make_pair(boot_image_live_objects_address + begin_offset,
                          boot_image_live_objects_address + end_offset);
  }

  void DumpDataBimgRelRoEntries(std::ostream& os) {
    os << ".data.bimg.rel.ro: ";
    if (oat_file_.GetBootImageRelocations().empty()) {
      os << "empty.\n\n";
      return;
    }

    os << oat_file_.GetBootImageRelocations().size() << " entries.\n";
    Runtime* runtime = Runtime::Current();
    if (runtime != nullptr && !runtime->GetHeap()->GetBootImageSpaces().empty()) {
      const std::vector<gc::space::ImageSpace*>& boot_image_spaces =
          runtime->GetHeap()->GetBootImageSpaces();
      ScopedObjectAccess soa(Thread::Current());
      auto live_objects = GetBootImageLiveObjectsDataRange(runtime->GetHeap());
      const uint8_t* live_objects_begin = live_objects.first;
      const uint8_t* live_objects_end = live_objects.second;
      for (const uint32_t& object_offset : oat_file_.GetBootImageRelocations()) {
        uint32_t entry_index = &object_offset - oat_file_.GetBootImageRelocations().data();
        uint32_t entry_offset = entry_index * sizeof(oat_file_.GetBootImageRelocations()[0]);
        os << StringPrintf("  0x%x: 0x%08x", entry_offset, object_offset);
        uint8_t* address = boot_image_spaces[0]->Begin() + object_offset;
        bool found = false;
        for (gc::space::ImageSpace* space : boot_image_spaces) {
          uint64_t local_offset = address - space->Begin();
          if (local_offset < space->GetImageHeader().GetImageSize()) {
            if (space->GetImageHeader().GetObjectsSection().Contains(local_offset)) {
              if (address >= live_objects_begin && address < live_objects_end) {
                size_t index =
                    (address - live_objects_begin) / sizeof(mirror::HeapReference<mirror::Object>);
                os << StringPrintf("   0x%08x BootImageLiveObject[%zu]",
                                   object_offset,
                                   index);
              } else {
                ObjPtr<mirror::Object> o = reinterpret_cast<mirror::Object*>(address);
                if (o->IsString()) {
                  os << "   String: " << o->AsString()->ToModifiedUtf8();
                } else if (o->IsClass()) {
                  os << "   Class: " << o->AsClass()->PrettyDescriptor();
                } else {
                  os << StringPrintf("   0x%08x %s",
                                     object_offset,
                                     o->GetClass()->PrettyDescriptor().c_str());
                }
              }
            } else if (space->GetImageHeader().GetMethodsSection().Contains(local_offset)) {
              ArtMethod* m = reinterpret_cast<ArtMethod*>(address);
              os << "   ArtMethod: " << m->PrettyMethod();
            } else {
              os << StringPrintf("   0x%08x <unexpected section in %s>",
                                 object_offset,
                                 space->GetImageFilename().c_str());
            }
            found = true;
            break;
          }
        }
        if (!found) {
          os << StringPrintf("   0x%08x <outside boot image spaces>", object_offset);
        }
        os << "\n";
      }
    } else {
      for (const uint32_t& object_offset : oat_file_.GetBootImageRelocations()) {
        uint32_t entry_index = &object_offset - oat_file_.GetBootImageRelocations().data();
        uint32_t entry_offset = entry_index * sizeof(oat_file_.GetBootImageRelocations()[0]);
        os << StringPrintf("  0x%x: 0x%08x\n", entry_offset, object_offset);
      }
    }
    os << "\n";
  }

  template <typename NameGetter>
  void DumpBssEntries(std::ostream& os,
                      const char* slot_type,
                      const IndexBssMapping* mapping,
                      uint32_t number_of_indexes,
                      size_t slot_size,
                      NameGetter name) {
    os << ".bss mapping for " << slot_type << ": ";
    if (mapping == nullptr) {
      os << "empty.\n";
      return;
    }
    size_t index_bits = IndexBssMappingEntry::IndexBits(number_of_indexes);
    size_t num_valid_indexes = 0u;
    for (const IndexBssMappingEntry& entry : *mapping) {
      num_valid_indexes += 1u + POPCOUNT(entry.GetMask(index_bits));
    }
    os << mapping->size() << " entries for " << num_valid_indexes << " valid indexes.\n";
    os << std::hex;
    for (const IndexBssMappingEntry& entry : *mapping) {
      uint32_t index = entry.GetIndex(index_bits);
      uint32_t mask = entry.GetMask(index_bits);
      size_t bss_offset = entry.bss_offset - POPCOUNT(mask) * slot_size;
      for (uint32_t n : LowToHighBits(mask)) {
        size_t current_index = index - (32u - index_bits) + n;
        os << "  0x" << bss_offset << ": " << slot_type << ": " << name(current_index) << "\n";
        bss_offset += slot_size;
      }
      DCHECK_EQ(bss_offset, entry.bss_offset);
      os << "  0x" << bss_offset << ": " << slot_type << ": " << name(index) << "\n";
    }
    os << std::dec;
  }

  const OatFile& oat_file_;
  const std::vector<const OatDexFile*> oat_dex_files_;
  const OatDumperOptions& options_;
  uint32_t resolved_addr2instr_;
  const InstructionSet instruction_set_;
  std::set<uintptr_t> offsets_;
  Disassembler* disassembler_;
  Stats stats_;
  std::unordered_set<const void*> seen_stats_objects_;
};

class ImageDumper {
 public:
  ImageDumper(std::ostream* os,
              gc::space::ImageSpace& image_space,
              const ImageHeader& image_header,
              OatDumperOptions* oat_dumper_options)
      : os_(os),
        vios_(os),
        indent1_(&vios_),
        image_space_(image_space),
        image_header_(image_header),
        oat_dumper_options_(oat_dumper_options) {}

  bool Dump() REQUIRES_SHARED(Locks::mutator_lock_) {
    std::ostream& os = *os_;
    std::ostream& indent_os = vios_.Stream();

    os << "MAGIC: " << image_header_.GetMagic() << "\n\n";

    os << "IMAGE LOCATION: " << image_space_.GetImageLocation() << "\n\n";

    os << "IMAGE BEGIN: " << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n";
    os << "IMAGE SIZE: " << image_header_.GetImageSize() << "\n";
    os << "IMAGE CHECKSUM: " << std::hex << image_header_.GetImageChecksum() << std::dec << "\n\n";

    os << "OAT CHECKSUM: " << StringPrintf("0x%08x\n\n", image_header_.GetOatChecksum()) << "\n";
    os << "OAT FILE BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatFileBegin()) << "\n";
    os << "OAT DATA BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatDataBegin()) << "\n";
    os << "OAT DATA END:" << reinterpret_cast<void*>(image_header_.GetOatDataEnd()) << "\n";
    os << "OAT FILE END:" << reinterpret_cast<void*>(image_header_.GetOatFileEnd()) << "\n\n";

    os << "BOOT IMAGE BEGIN: " << reinterpret_cast<void*>(image_header_.GetBootImageBegin())
        << "\n";
    os << "BOOT IMAGE SIZE: " << image_header_.GetBootImageSize() << "\n\n";

    for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) {
      auto section = static_cast<ImageHeader::ImageSections>(i);
      os << "IMAGE SECTION " << section << ": " << image_header_.GetImageSection(section) << "\n\n";
    }

    {
      os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots().Ptr()) << "\n";
      static_assert(arraysize(image_roots_descriptions_) ==
          static_cast<size_t>(ImageHeader::kImageRootsMax), "sizes must match");
      DCHECK_LE(image_header_.GetImageRoots()->GetLength(), ImageHeader::kImageRootsMax);
      for (int32_t i = 0, size = image_header_.GetImageRoots()->GetLength(); i != size; ++i) {
        ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
        const char* image_root_description = image_roots_descriptions_[i];
        ObjPtr<mirror::Object> image_root_object = image_header_.GetImageRoot(image_root);
        indent_os << StringPrintf("%s: %p\n", image_root_description, image_root_object.Ptr());
        if (image_root_object != nullptr && image_root_object->IsObjectArray()) {
          ObjPtr<mirror::ObjectArray<mirror::Object>> image_root_object_array
              = image_root_object->AsObjectArray<mirror::Object>();
          ScopedIndentation indent2(&vios_);
          for (int j = 0; j < image_root_object_array->GetLength(); j++) {
            ObjPtr<mirror::Object> value = image_root_object_array->Get(j);
            size_t run = 0;
            for (int32_t k = j + 1; k < image_root_object_array->GetLength(); k++) {
              if (value == image_root_object_array->Get(k)) {
                run++;
              } else {
                break;
              }
            }
            if (run == 0) {
              indent_os << StringPrintf("%d: ", j);
            } else {
              indent_os << StringPrintf("%d to %zd: ", j, j + run);
              j = j + run;
            }
            if (value != nullptr) {
              PrettyObjectValue(indent_os, value->GetClass(), value);
            } else {
              indent_os << j << ": null\n";
            }
          }
        }
      }
    }

    {
      os << "METHOD ROOTS\n";
      static_assert(arraysize(image_methods_descriptions_) ==
          static_cast<size_t>(ImageHeader::kImageMethodsCount), "sizes must match");
      for (int i = 0; i < ImageHeader::kImageMethodsCount; i++) {
        auto image_root = static_cast<ImageHeader::ImageMethod>(i);
        const char* description = image_methods_descriptions_[i];
        auto* image_method = image_header_.GetImageMethod(image_root);
        indent_os << StringPrintf("%s: %p\n", description, image_method);
      }
    }
    os << "\n";

    Runtime* const runtime = Runtime::Current();
    std::string image_filename = image_space_.GetImageFilename();
    std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(image_filename);
    os << "OAT LOCATION: " << oat_location;
    os << "\n";
    std::string error_msg;
    const OatFile* oat_file = image_space_.GetOatFile();
    if (oat_file == nullptr) {
      oat_file = runtime->GetOatFileManager().FindOpenedOatFileFromOatLocation(oat_location);
    }
    if (oat_file == nullptr) {
      oat_file = OatFile::Open(/*zip_fd=*/ -1,
                               oat_location,
                               oat_location,
                               /*executable=*/ false,
                               /*low_4gb=*/ false,
                               &error_msg);
    }
    if (oat_file == nullptr) {
      os << "OAT FILE NOT FOUND: " << error_msg << "\n";
      return EXIT_FAILURE;
    }
    os << "\n";

    stats_.oat_file_bytes = oat_file->Size();
    stats_.oat_file_stats.AddBytes(oat_file->Size());

    oat_dumper_.reset(new OatDumper(*oat_file, *oat_dumper_options_));

    for (const OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) {
      CHECK(oat_dex_file != nullptr);
      stats_.oat_dex_file_sizes.push_back(std::make_pair(oat_dex_file->GetDexFileLocation(),
                                                         oat_dex_file->FileSize()));
    }

    os << "OBJECTS:\n" << std::flush;

    // Loop through the image space and dump its objects.
    gc::Heap* heap = runtime->GetHeap();
    Thread* self = Thread::Current();
    {
      {
        WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
        heap->FlushAllocStack();
      }
      // Since FlushAllocStack() above resets the (active) allocation
      // stack. Need to revoke the thread-local allocation stacks that
      // point into it.
      ScopedThreadSuspension sts(self, kNative);
      ScopedSuspendAll ssa(__FUNCTION__);
      heap->RevokeAllThreadLocalAllocationStacks(self);
    }
    {
      auto dump_visitor = [&](mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
        DumpObject(obj);
      };
      ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
      // Dump the normal objects before ArtMethods.
      image_space_.GetLiveBitmap()->Walk(dump_visitor);
      indent_os << "\n";
      // TODO: Dump fields.
      // Dump methods after.
      image_header_.VisitPackedArtMethods([&](ArtMethod& method)
          REQUIRES_SHARED(Locks::mutator_lock_) {
        std::ostream& indent_os = vios_.Stream();
        indent_os << &method << " " << " ArtMethod: " << method.PrettyMethod() << "\n";
        DumpMethod(&method, indent_os);
        indent_os << "\n";
      },  image_space_.Begin(), image_header_.GetPointerSize());
      // Dump the large objects separately.
      heap->GetLargeObjectsSpace()->GetLiveBitmap()->Walk(dump_visitor);
      indent_os << "\n";
    }
    os << "STATS:\n" << std::flush;
    std::unique_ptr<File> file(OS::OpenFileForReading(image_filename.c_str()));
    size_t data_size = image_header_.GetDataSize();  // stored size in file.
    if (file == nullptr) {
      LOG(WARNING) << "Failed to find image in " << image_filename;
    } else {
      size_t file_bytes = file->GetLength();
      // If the image is compressed, adjust to decompressed size.
      size_t uncompressed_size = image_header_.GetImageSize() - sizeof(ImageHeader);
      if (!image_header_.HasCompressedBlock()) {
        DCHECK_EQ(uncompressed_size, data_size) << "Sizes should match for uncompressed image";
      }
      file_bytes += uncompressed_size - data_size;
      stats_.art_file_stats.AddBytes(file_bytes);
      stats_.art_file_stats["Header"].AddBytes(sizeof(ImageHeader));
    }

    size_t pointer_size = static_cast<size_t>(image_header_.GetPointerSize());
    CHECK_ALIGNED(image_header_.GetFieldsSection().Offset(), 4);
    CHECK_ALIGNED_PARAM(image_header_.GetMethodsSection().Offset(), pointer_size);
    CHECK_ALIGNED(image_header_.GetInternedStringsSection().Offset(), 8);
    CHECK_ALIGNED(image_header_.GetImageBitmapSection().Offset(), kPageSize);

    for (size_t i = 0; i < ImageHeader::ImageSections::kSectionCount; i++) {
      ImageHeader::ImageSections index = ImageHeader::ImageSections(i);
      const char* name = ImageHeader::GetImageSectionName(index);
      stats_.art_file_stats[name].AddBytes(image_header_.GetImageSection(index).Size());
    }

    stats_.object_stats.AddBytes(image_header_.GetObjectsSection().Size());
    stats_.Dump(os);
    os << "\n";

    os << std::flush;

    return oat_dumper_->Dump(os);
  }

 private:
  static void PrettyObjectValue(std::ostream& os,
                                ObjPtr<mirror::Class> type,
                                ObjPtr<mirror::Object> value)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    CHECK(type != nullptr);
    if (value == nullptr) {
      os << StringPrintf("null   %s\n", type->PrettyDescriptor().c_str());
    } else if (type->IsStringClass()) {
      ObjPtr<mirror::String> string = value->AsString();
      os << StringPrintf("%p   String: %s\n",
                         string.Ptr(),
                         PrintableString(string->ToModifiedUtf8().c_str()).c_str());
    } else if (type->IsClassClass()) {
      ObjPtr<mirror::Class> klass = value->AsClass();
      os << StringPrintf("%p   Class: %s\n",
                         klass.Ptr(),
                         mirror::Class::PrettyDescriptor(klass).c_str());
    } else {
      os << StringPrintf("%p   %s\n", value.Ptr(), type->PrettyDescriptor().c_str());
    }
  }

  static void PrintField(std::ostream& os, ArtField* field, ObjPtr<mirror::Object> obj)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    os << StringPrintf("%s: ", field->GetName());
    switch (field->GetTypeAsPrimitiveType()) {
      case Primitive::kPrimLong:
        os << StringPrintf("%" PRId64 " (0x%" PRIx64 ")\n", field->Get64(obj), field->Get64(obj));
        break;
      case Primitive::kPrimDouble:
        os << StringPrintf("%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj));
        break;
      case Primitive::kPrimFloat:
        os << StringPrintf("%f (%a)\n", field->GetFloat(obj), field->GetFloat(obj));
        break;
      case Primitive::kPrimInt:
        os << StringPrintf("%d (0x%x)\n", field->Get32(obj), field->Get32(obj));
        break;
      case Primitive::kPrimChar:
        os << StringPrintf("%u (0x%x)\n", field->GetChar(obj), field->GetChar(obj));
        break;
      case Primitive::kPrimShort:
        os << StringPrintf("%d (0x%x)\n", field->GetShort(obj), field->GetShort(obj));
        break;
      case Primitive::kPrimBoolean:
        os << StringPrintf("%s (0x%x)\n", field->GetBoolean(obj) ? "true" : "false",
            field->GetBoolean(obj));
        break;
      case Primitive::kPrimByte:
        os << StringPrintf("%d (0x%x)\n", field->GetByte(obj), field->GetByte(obj));
        break;
      case Primitive::kPrimNot: {
        // Get the value, don't compute the type unless it is non-null as we don't want
        // to cause class loading.
        ObjPtr<mirror::Object> value = field->GetObj(obj);
        if (value == nullptr) {
          os << StringPrintf("null   %s\n", PrettyDescriptor(field->GetTypeDescriptor()).c_str());
        } else {
          // Grab the field type without causing resolution.
          ObjPtr<mirror::Class> field_type = field->LookupResolvedType();
          if (field_type != nullptr) {
            PrettyObjectValue(os, field_type, value);
          } else {
            os << StringPrintf("%p   %s\n",
                               value.Ptr(),
                               PrettyDescriptor(field->GetTypeDescriptor()).c_str());
          }
        }
        break;
      }
      default:
        os << "unexpected field type: " << field->GetTypeDescriptor() << "\n";
        break;
    }
  }

  static void DumpFields(std::ostream& os, mirror::Object* obj, ObjPtr<mirror::Class> klass)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    ObjPtr<mirror::Class> super = klass->GetSuperClass();
    if (super != nullptr) {
      DumpFields(os, obj, super);
    }
    for (ArtField& field : klass->GetIFields()) {
      PrintField(os, &field, obj);
    }
  }

  bool InDumpSpace(const mirror::Object* object) {
    return image_space_.Contains(object);
  }

  const void* GetQuickOatCodeBegin(ArtMethod* m) REQUIRES_SHARED(Locks::mutator_lock_) {
    const void* quick_code = m->GetEntryPointFromQuickCompiledCodePtrSize(
        image_header_.GetPointerSize());
    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
    if (class_linker->IsQuickResolutionStub(quick_code) ||
        class_linker->IsQuickToInterpreterBridge(quick_code) ||
        class_linker->IsNterpTrampoline(quick_code) ||
        class_linker->IsQuickGenericJniStub(quick_code) ||
        class_linker->IsJniDlsymLookupStub(quick_code) ||
        class_linker->IsJniDlsymLookupCriticalStub(quick_code)) {
      quick_code = oat_dumper_->GetQuickOatCode(m);
    }
    if (oat_dumper_->GetInstructionSet() == InstructionSet::kThumb2) {
      quick_code = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(quick_code) & ~0x1);
    }
    return quick_code;
  }

  uint32_t GetQuickOatCodeSize(ArtMethod* m)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetQuickOatCodeBegin(m));
    if (oat_code_begin == nullptr) {
      return 0;
    }
    OatQuickMethodHeader* method_header = reinterpret_cast<OatQuickMethodHeader*>(
        reinterpret_cast<uintptr_t>(oat_code_begin) - sizeof(OatQuickMethodHeader));
    return method_header->GetCodeSize();
  }

  const void* GetQuickOatCodeEnd(ArtMethod* m)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetQuickOatCodeBegin(m));
    if (oat_code_begin == nullptr) {
      return nullptr;
    }
    return oat_code_begin + GetQuickOatCodeSize(m);
  }

  void DumpObject(mirror::Object* obj) REQUIRES_SHARED(Locks::mutator_lock_) {
    DCHECK(obj != nullptr);
    if (!InDumpSpace(obj)) {
      return;
    }

    std::ostream& os = vios_.Stream();

    ObjPtr<mirror::Class> obj_class = obj->GetClass();
    if (obj_class->IsArrayClass()) {
      os << StringPrintf("%p: %s length:%d\n", obj, obj_class->PrettyDescriptor().c_str(),
                         obj->AsArray()->GetLength());
    } else if (obj->IsClass()) {
      ObjPtr<mirror::Class> klass = obj->AsClass();
      os << StringPrintf("%p: java.lang.Class \"%s\" (",
                         obj,
                         mirror::Class::PrettyDescriptor(klass).c_str())
         << klass->GetStatus() << ")\n";
    } else if (obj_class->IsStringClass()) {
      os << StringPrintf("%p: java.lang.String %s\n",
                         obj,
                         PrintableString(obj->AsString()->ToModifiedUtf8().c_str()).c_str());
    } else {
      os << StringPrintf("%p: %s\n", obj, obj_class->PrettyDescriptor().c_str());
    }
    ScopedIndentation indent1(&vios_);
    DumpFields(os, obj, obj_class);
    if (obj->IsObjectArray()) {
      ObjPtr<mirror::ObjectArray<mirror::Object>> obj_array = obj->AsObjectArray<mirror::Object>();
      for (int32_t i = 0, length = obj_array->GetLength(); i < length; i++) {
        ObjPtr<mirror::Object> value = obj_array->Get(i);
        size_t run = 0;
        for (int32_t j = i + 1; j < length; j++) {
          if (value == obj_array->Get(j)) {
            run++;
          } else {
            break;
          }
        }
        if (run == 0) {
          os << StringPrintf("%d: ", i);
        } else {
          os << StringPrintf("%d to %zd: ", i, i + run);
          i = i + run;
        }
        ObjPtr<mirror::Class> value_class =
            (value == nullptr) ? obj_class->GetComponentType() : value->GetClass();
        PrettyObjectValue(os, value_class, value);
      }
    } else if (obj->IsClass()) {
      ObjPtr<mirror::Class> klass = obj->AsClass();

      if (kBitstringSubtypeCheckEnabled) {
        os << "SUBTYPE_CHECK_BITS: ";
        SubtypeCheck<ObjPtr<mirror::Class>>::Dump(klass, os);
        os << "\n";
      }

      if (klass->NumStaticFields() != 0) {
        os << "STATICS:\n";
        ScopedIndentation indent2(&vios_);
        for (ArtField& field : klass->GetSFields()) {
          PrintField(os, &field, field.GetDeclaringClass());
        }
      }
    }
    std::string temp;
    const char* desc = obj_class->GetDescriptor(&temp);
    desc = stats_.descriptors.emplace(desc).first->c_str();  // Dedup and keep alive.
    stats_.object_stats[desc].AddBytes(obj->SizeOf());
  }

  void DumpMethod(ArtMethod* method, std::ostream& indent_os)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    DCHECK(method != nullptr);
    const PointerSize pointer_size = image_header_.GetPointerSize();
    if (method->IsNative()) {
      const void* quick_oat_code_begin = GetQuickOatCodeBegin(method);
      bool first_occurrence;
      uint32_t quick_oat_code_size = GetQuickOatCodeSize(method);
      ComputeOatSize(quick_oat_code_begin, &first_occurrence);
      if (first_occurrence) {
        stats_.oat_file_stats["native_code"].AddBytes(quick_oat_code_size);
      }
      if (quick_oat_code_begin != method->GetEntryPointFromQuickCompiledCodePtrSize(
          image_header_.GetPointerSize())) {
        indent_os << StringPrintf("OAT CODE: %p\n", quick_oat_code_begin);
      }
    } else if (method->IsAbstract() || method->IsClassInitializer()) {
      // Don't print information for these.
    } else if (method->IsRuntimeMethod()) {
      if (method == Runtime::Current()->GetResolutionMethod()) {
        const void* resolution_trampoline =
            method->GetEntryPointFromQuickCompiledCodePtrSize(image_header_.GetPointerSize());
        indent_os << StringPrintf("Resolution trampoline: %p\n", resolution_trampoline);
        const void* critical_native_resolution_trampoline =
            method->GetEntryPointFromJniPtrSize(image_header_.GetPointerSize());
        indent_os << StringPrintf("Resolution trampoline for @CriticalNative: %p\n",
                                  critical_native_resolution_trampoline);
      } else {
        ImtConflictTable* table = method->GetImtConflictTable(image_header_.GetPointerSize());
        if (table != nullptr) {
          indent_os << "IMT conflict table " << table << " method: ";
          for (size_t i = 0, count = table->NumEntries(pointer_size); i < count; ++i) {
            indent_os << ArtMethod::PrettyMethod(table->GetImplementationMethod(i, pointer_size))
                      << " ";
          }
        }
      }
    } else {
      CodeItemDataAccessor code_item_accessor(method->DexInstructionData());
      size_t dex_instruction_bytes = code_item_accessor.InsnsSizeInCodeUnits() * 2;
      stats_.dex_instruction_bytes += dex_instruction_bytes;

      const void* quick_oat_code_begin = GetQuickOatCodeBegin(method);
      const void* quick_oat_code_end = GetQuickOatCodeEnd(method);

      bool first_occurrence;
      size_t vmap_table_bytes = 0u;
      if (quick_oat_code_begin != nullptr) {
        OatQuickMethodHeader* method_header = reinterpret_cast<OatQuickMethodHeader*>(
            reinterpret_cast<uintptr_t>(quick_oat_code_begin) - sizeof(OatQuickMethodHeader));
        vmap_table_bytes = ComputeOatSize(method_header->GetOptimizedCodeInfoPtr(),
                                          &first_occurrence);
        if (first_occurrence) {
          stats_.vmap_table_bytes += vmap_table_bytes;
        }
      }

      uint32_t quick_oat_code_size = GetQuickOatCodeSize(method);
      ComputeOatSize(quick_oat_code_begin, &first_occurrence);
      if (first_occurrence) {
        stats_.managed_code_bytes += quick_oat_code_size;
        art::Stats& managed_code_stats = stats_.oat_file_stats["managed_code"];
        managed_code_stats.AddBytes(quick_oat_code_size);
        if (method->IsConstructor()) {
          if (method->IsStatic()) {
            managed_code_stats["class_initializer"].AddBytes(quick_oat_code_size);
          } else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
            managed_code_stats["large_initializer"].AddBytes(quick_oat_code_size);
          }
        } else if (dex_instruction_bytes > kLargeMethodDexBytes) {
          managed_code_stats["large_method"].AddBytes(quick_oat_code_size);
        }
      }
      stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size;

      uint32_t method_access_flags = method->GetAccessFlags();

      indent_os << StringPrintf("OAT CODE: %p-%p\n", quick_oat_code_begin, quick_oat_code_end);
      indent_os << StringPrintf("SIZE: Dex Instructions=%zd StackMaps=%zd AccessFlags=0x%x\n",
                                dex_instruction_bytes,
                                vmap_table_bytes,
                                method_access_flags);

      size_t total_size = dex_instruction_bytes +
          vmap_table_bytes + quick_oat_code_size + ArtMethod::Size(image_header_.GetPointerSize());

      double expansion =
      static_cast<double>(quick_oat_code_size) / static_cast<double>(dex_instruction_bytes);
      stats_.ComputeOutliers(total_size, expansion, method);
    }
  }

  std::set<const void*> already_seen_;
  // Compute the size of the given data within the oat file and whether this is the first time
  // this data has been requested
  size_t ComputeOatSize(const void* oat_data, bool* first_occurrence) {
    if (already_seen_.count(oat_data) == 0) {
      *first_occurrence = true;
      already_seen_.insert(oat_data);
    } else {
      *first_occurrence = false;
    }
    return oat_dumper_->ComputeSize(oat_data);
  }

 public:
  struct Stats {
    art::Stats art_file_stats;
    art::Stats oat_file_stats;
    art::Stats object_stats;
    std::set<std::string> descriptors;

    size_t oat_file_bytes = 0u;
    size_t managed_code_bytes = 0u;
    size_t managed_code_bytes_ignoring_deduplication = 0u;

    size_t vmap_table_bytes = 0u;

    size_t dex_instruction_bytes = 0u;

    std::vector<ArtMethod*> method_outlier;
    std::vector<size_t> method_outlier_size;
    std::vector<double> method_outlier_expansion;
    std::vector<std::pair<std::string, size_t>> oat_dex_file_sizes;

    Stats() {}

    double PercentOfOatBytes(size_t size) {
      return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100;
    }

    void ComputeOutliers(size_t total_size, double expansion, ArtMethod* method) {
      method_outlier_size.push_back(total_size);
      method_outlier_expansion.push_back(expansion);
      method_outlier.push_back(method);
    }

    void DumpOutliers(std::ostream& os)
        REQUIRES_SHARED(Locks::mutator_lock_) {
      size_t sum_of_sizes = 0;
      size_t sum_of_sizes_squared = 0;
      size_t sum_of_expansion = 0;
      size_t sum_of_expansion_squared = 0;
      size_t n = method_outlier_size.size();
      if (n <= 1) {
        return;
      }
      for (size_t i = 0; i < n; i++) {
        size_t cur_size = method_outlier_size[i];
        sum_of_sizes += cur_size;
        sum_of_sizes_squared += cur_size * cur_size;
        double cur_expansion = method_outlier_expansion[i];
        sum_of_expansion += cur_expansion;
        sum_of_expansion_squared += cur_expansion * cur_expansion;
      }
      size_t size_mean = sum_of_sizes / n;
      size_t size_variance = (sum_of_sizes_squared - sum_of_sizes * size_mean) / (n - 1);
      double expansion_mean = sum_of_expansion / n;
      double expansion_variance =
          (sum_of_expansion_squared - sum_of_expansion * expansion_mean) / (n - 1);

      // Dump methods whose size is a certain number of standard deviations from the mean
      size_t dumped_values = 0;
      size_t skipped_values = 0;
      for (size_t i = 100; i > 0; i--) {  // i is the current number of standard deviations
        size_t cur_size_variance = i * i * size_variance;
        bool first = true;
        for (size_t j = 0; j < n; j++) {
          size_t cur_size = method_outlier_size[j];
          if (cur_size > size_mean) {
            size_t cur_var = cur_size - size_mean;
            cur_var = cur_var * cur_var;
            if (cur_var > cur_size_variance) {
              if (dumped_values > 20) {
                if (i == 1) {
                  skipped_values++;
                } else {
                  i = 2;  // jump to counting for 1 standard deviation
                  break;
                }
              } else {
                if (first) {
                  os << "\nBig methods (size > " << i << " standard deviations the norm):\n";
                  first = false;
                }
                os << ArtMethod::PrettyMethod(method_outlier[j]) << " requires storage of "
                    << PrettySize(cur_size) << "\n";
                method_outlier_size[j] = 0;  // don't consider this method again
                dumped_values++;
              }
            }
          }
        }
      }
      if (skipped_values > 0) {
        os << "... skipped " << skipped_values
           << " methods with size > 1 standard deviation from the norm\n";
      }
      os << std::flush;

      // Dump methods whose expansion is a certain number of standard deviations from the mean
      dumped_values = 0;
      skipped_values = 0;
      for (size_t i = 10; i > 0; i--) {  // i is the current number of standard deviations
        double cur_expansion_variance = i * i * expansion_variance;
        bool first = true;
        for (size_t j = 0; j < n; j++) {
          double cur_expansion = method_outlier_expansion[j];
          if (cur_expansion > expansion_mean) {
            size_t cur_var = cur_expansion - expansion_mean;
            cur_var = cur_var * cur_var;
            if (cur_var > cur_expansion_variance) {
              if (dumped_values > 20) {
                if (i == 1) {
                  skipped_values++;
                } else {
                  i = 2;  // jump to counting for 1 standard deviation
                  break;
                }
              } else {
                if (first) {
                  os << "\nLarge expansion methods (size > " << i
                      << " standard deviations the norm):\n";
                  first = false;
                }
                os << ArtMethod::PrettyMethod(method_outlier[j]) << " expanded code by "
                   << cur_expansion << "\n";
                method_outlier_expansion[j] = 0.0;  // don't consider this method again
                dumped_values++;
              }
            }
          }
        }
      }
      if (skipped_values > 0) {
        os << "... skipped " << skipped_values
           << " methods with expansion > 1 standard deviation from the norm\n";
      }
      os << "\n" << std::flush;
    }

    void Dump(std::ostream& os)
        REQUIRES_SHARED(Locks::mutator_lock_) {
      VariableIndentationOutputStream vios(&os);
      art_file_stats.DumpSizes(vios, "ArtFile");
      os << "\n" << std::flush;
      object_stats.DumpSizes(vios, "Objects");
      os << "\n" << std::flush;
      oat_file_stats.DumpSizes(vios, "OatFile");
      os << "\n" << std::flush;

      for (const std::pair<std::string, size_t>& oat_dex_file_size : oat_dex_file_sizes) {
        os << StringPrintf("%s = %zd (%2.0f%% of oat file bytes)\n",
                           oat_dex_file_size.first.c_str(), oat_dex_file_size.second,
                           PercentOfOatBytes(oat_dex_file_size.second));
      }

      os << "\n" << StringPrintf("vmap_table_bytes       = %7zd (%2.0f%% of oat file bytes)\n\n",
                                 vmap_table_bytes, PercentOfOatBytes(vmap_table_bytes))
         << std::flush;

      os << StringPrintf("dex_instruction_bytes = %zd\n", dex_instruction_bytes)
         << StringPrintf("managed_code_bytes expansion = %.2f (ignoring deduplication %.2f)\n\n",
                         static_cast<double>(managed_code_bytes) /
                             static_cast<double>(dex_instruction_bytes),
                         static_cast<double>(managed_code_bytes_ignoring_deduplication) /
                             static_cast<double>(dex_instruction_bytes))
         << std::flush;

      DumpOutliers(os);
    }
  } stats_;

 private:
  enum {
    // Number of bytes for a constructor to be considered large. Based on the 1000 basic block
    // threshold, we assume 2 bytes per instruction and 2 instructions per block.
    kLargeConstructorDexBytes = 4000,
    // Number of bytes for a method to be considered large. Based on the 4000 basic block
    // threshold, we assume 2 bytes per instruction and 2 instructions per block.
    kLargeMethodDexBytes = 16000
  };

  // For performance, use the *os_ directly for anything that doesn't need indentation
  // and prepare an indentation stream with default indentation 1.
  std::ostream* os_;
  VariableIndentationOutputStream vios_;
  ScopedIndentation indent1_;

  gc::space::ImageSpace& image_space_;
  const ImageHeader& image_header_;
  std::unique_ptr<OatDumper> oat_dumper_;
  OatDumperOptions* oat_dumper_options_;

  DISALLOW_COPY_AND_ASSIGN(ImageDumper);
};

static int DumpImage(gc::space::ImageSpace* image_space,
                     OatDumperOptions* options,
                     std::ostream* os) REQUIRES_SHARED(Locks::mutator_lock_) {
  const ImageHeader& image_header = image_space->GetImageHeader();
  if (!image_header.IsValid()) {
    LOG(ERROR) << "Invalid image header " << image_space->GetImageLocation();
    return EXIT_FAILURE;
  }
  ImageDumper image_dumper(os, *image_space, image_header, options);
  if (!image_dumper.Dump()) {
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}

static int DumpImages(Runtime* runtime, OatDumperOptions* options, std::ostream* os) {
  // Dumping the image, no explicit class loader.
  ScopedNullHandle<mirror::ClassLoader> null_class_loader;
  options->class_loader_ = &null_class_loader;

  ScopedObjectAccess soa(Thread::Current());
  if (options->app_image_ != nullptr) {
    if (options->app_oat_ == nullptr) {
      LOG(ERROR) << "Can not dump app image without app oat file";
      return EXIT_FAILURE;
    }
    // We can't know if the app image is 32 bits yet, but it contains pointers into the oat file.
    // We need to map the oat file in the low 4gb or else the fixup wont be able to fit oat file
    // pointers into 32 bit pointer sized ArtMethods.
    std::string error_msg;
    std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                    options->app_oat_,
                                                    options->app_oat_,
                                                    /*executable=*/ false,
                                                    /*low_4gb=*/ true,
                                                    &error_msg));
    if (oat_file == nullptr) {
      LOG(ERROR) << "Failed to open oat file " << options->app_oat_ << " with error " << error_msg;
      return EXIT_FAILURE;
    }
    std::unique_ptr<gc::space::ImageSpace> space(
        gc::space::ImageSpace::CreateFromAppImage(options->app_image_, oat_file.get(), &error_msg));
    if (space == nullptr) {
      LOG(ERROR) << "Failed to open app image " << options->app_image_ << " with error "
                 << error_msg;
      return EXIT_FAILURE;
    }
    // Open dex files for the image.
    std::vector<std::unique_ptr<const DexFile>> dex_files;
    if (!runtime->GetClassLinker()->OpenImageDexFiles(space.get(), &dex_files, &error_msg)) {
      LOG(ERROR) << "Failed to open app image dex files " << options->app_image_ << " with error "
                 << error_msg;
      return EXIT_FAILURE;
    }
    // Dump the actual image.
    int result = DumpImage(space.get(), options, os);
    if (result != EXIT_SUCCESS) {
      return result;
    }
    // Fall through to dump the boot images.
  }

  gc::Heap* heap = runtime->GetHeap();
  if (!heap->HasBootImageSpace()) {
    LOG(ERROR) << "No image spaces";
    return EXIT_FAILURE;
  }
  for (gc::space::ImageSpace* image_space : heap->GetBootImageSpaces()) {
    int result = DumpImage(image_space, options, os);
    if (result != EXIT_SUCCESS) {
      return result;
    }
  }
  return EXIT_SUCCESS;
}

static jobject InstallOatFile(Runtime* runtime,
                              std::unique_ptr<OatFile> oat_file,
                              std::vector<const DexFile*>* class_path)
    REQUIRES_SHARED(Locks::mutator_lock_) {
  Thread* self = Thread::Current();
  CHECK(self != nullptr);
  // Need well-known-classes.
  WellKnownClasses::Init(self->GetJniEnv());

  // Open dex files.
  OatFile* oat_file_ptr = oat_file.get();
  ClassLinker* class_linker = runtime->GetClassLinker();
  runtime->GetOatFileManager().RegisterOatFile(std::move(oat_file));
  for (const OatDexFile* odf : oat_file_ptr->GetOatDexFiles()) {
    std::string error_msg;
    const DexFile* const dex_file = OpenDexFile(odf, &error_msg);
    CHECK(dex_file != nullptr) << error_msg;
    class_path->push_back(dex_file);
  }

  // Need a class loader. Fake that we're a compiler.
  // Note: this will run initializers through the unstarted runtime, so make sure it's
  //       initialized.
  interpreter::UnstartedRuntime::Initialize();

  jobject class_loader = class_linker->CreatePathClassLoader(self, *class_path);

  // Need to register dex files to get a working dex cache.
  for (const DexFile* dex_file : *class_path) {
    ObjPtr<mirror::DexCache> dex_cache = class_linker->RegisterDexFile(
        *dex_file, self->DecodeJObject(class_loader)->AsClassLoader());
    CHECK(dex_cache != nullptr);
  }

  return class_loader;
}

static int DumpOatWithRuntime(Runtime* runtime,
                              std::unique_ptr<OatFile> oat_file,
                              OatDumperOptions* options,
                              std::ostream* os) {
  CHECK(runtime != nullptr && oat_file != nullptr && options != nullptr);
  ScopedObjectAccess soa(Thread::Current());

  OatFile* oat_file_ptr = oat_file.get();
  std::vector<const DexFile*> class_path;
  jobject class_loader = InstallOatFile(runtime, std::move(oat_file), &class_path);

  // Use the class loader while dumping.
  StackHandleScope<1> scope(soa.Self());
  Handle<mirror::ClassLoader> loader_handle = scope.NewHandle(
      soa.Decode<mirror::ClassLoader>(class_loader));
  options->class_loader_ = &loader_handle;

  OatDumper oat_dumper(*oat_file_ptr, *options);
  bool success = oat_dumper.Dump(*os);
  return (success) ? EXIT_SUCCESS : EXIT_FAILURE;
}

static int DumpOatWithoutRuntime(OatFile* oat_file, OatDumperOptions* options, std::ostream* os) {
  CHECK(oat_file != nullptr && options != nullptr);
  // No image = no class loader.
  ScopedNullHandle<mirror::ClassLoader> null_class_loader;
  options->class_loader_ = &null_class_loader;

  OatDumper oat_dumper(*oat_file, *options);
  bool success = oat_dumper.Dump(*os);
  return (success) ? EXIT_SUCCESS : EXIT_FAILURE;
}

static int DumpOat(Runtime* runtime,
                   const char* oat_filename,
                   const char* dex_filename,
                   OatDumperOptions* options,
                   std::ostream* os) {
  if (dex_filename == nullptr) {
    LOG(WARNING) << "No dex filename provided, "
                 << "oatdump might fail if the oat file does not contain the dex code.";
  }
  std::string dex_filename_str((dex_filename != nullptr) ? dex_filename : "");
  ArrayRef<const std::string> dex_filenames(&dex_filename_str,
                                            /*size=*/ (dex_filename != nullptr) ? 1u : 0u);
  std::string error_msg;
  std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                  oat_filename,
                                                  oat_filename,
                                                  /*executable=*/ false,
                                                  /*low_4gb=*/ false,
                                                  dex_filenames,
                                                  /*reservation=*/ nullptr,
                                                  &error_msg));
  if (oat_file == nullptr) {
    LOG(ERROR) << "Failed to open oat file from '" << oat_filename << "': " << error_msg;
    return EXIT_FAILURE;
  }

  if (runtime != nullptr) {
    return DumpOatWithRuntime(runtime, std::move(oat_file), options, os);
  } else {
    return DumpOatWithoutRuntime(oat_file.get(), options, os);
  }
}

static int SymbolizeOat(const char* oat_filename,
                        const char* dex_filename,
                        std::string& output_name,
                        bool no_bits) {
  std::string dex_filename_str((dex_filename != nullptr) ? dex_filename : "");
  ArrayRef<const std::string> dex_filenames(&dex_filename_str,
                                            /*size=*/ (dex_filename != nullptr) ? 1u : 0u);
  std::string error_msg;
  std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                  oat_filename,
                                                  oat_filename,
                                                  /*executable=*/ false,
                                                  /*low_4gb=*/ false,
                                                  dex_filenames,
                                                  /*reservation=*/ nullptr,
                                                  &error_msg));
  if (oat_file == nullptr) {
    LOG(ERROR) << "Failed to open oat file from '" << oat_filename << "': " << error_msg;
    return EXIT_FAILURE;
  }

  bool result;
  // Try to produce an ELF file of the same type. This is finicky, as we have used 32-bit ELF
  // files for 64-bit code in the past.
  if (Is64BitInstructionSet(oat_file->GetOatHeader().GetInstructionSet())) {
    OatSymbolizer<ElfTypes64> oat_symbolizer(oat_file.get(), output_name, no_bits);
    result = oat_symbolizer.Symbolize();
  } else {
    OatSymbolizer<ElfTypes32> oat_symbolizer(oat_file.get(), output_name, no_bits);
    result = oat_symbolizer.Symbolize();
  }
  if (!result) {
    LOG(ERROR) << "Failed to symbolize";
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

class IMTDumper {
 public:
  static bool Dump(Runtime* runtime,
                   const std::string& imt_file,
                   bool dump_imt_stats,
                   const char* oat_filename,
                   const char* dex_filename) {
    Thread* self = Thread::Current();

    ScopedObjectAccess soa(self);
    StackHandleScope<1> scope(self);
    MutableHandle<mirror::ClassLoader> class_loader = scope.NewHandle<mirror::ClassLoader>(nullptr);
    std::vector<const DexFile*> class_path;

    if (oat_filename != nullptr) {
    std::string dex_filename_str((dex_filename != nullptr) ? dex_filename : "");
    ArrayRef<const std::string> dex_filenames(&dex_filename_str,
                                              /*size=*/ (dex_filename != nullptr) ? 1u : 0u);
      std::string error_msg;
      std::unique_ptr<OatFile> oat_file(OatFile::Open(/*zip_fd=*/ -1,
                                                      oat_filename,
                                                      oat_filename,
                                                      /*executable=*/ false,
                                                      /*low_4gb=*/false,
                                                      dex_filenames,
                                                      /*reservation=*/ nullptr,
                                                      &error_msg));
      if (oat_file == nullptr) {
        LOG(ERROR) << "Failed to open oat file from '" << oat_filename << "': " << error_msg;
        return false;
      }

      class_loader.Assign(soa.Decode<mirror::ClassLoader>(
          InstallOatFile(runtime, std::move(oat_file), &class_path)));
    } else {
      class_loader.Assign(nullptr);  // Boot classloader. Just here for explicit documentation.
      class_path = runtime->GetClassLinker()->GetBootClassPath();
    }

    if (!imt_file.empty()) {
      return DumpImt(runtime, imt_file, class_loader);
    }

    if (dump_imt_stats) {
      return DumpImtStats(runtime, class_path, class_loader);
    }

    LOG(FATAL) << "Should not reach here";
    UNREACHABLE();
  }

 private:
  static bool DumpImt(Runtime* runtime,
                      const std::string& imt_file,
                      Handle<mirror::ClassLoader> h_class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    std::vector<std::string> lines = ReadCommentedInputFromFile(imt_file);
    std::unordered_set<std::string> prepared;

    for (const std::string& line : lines) {
      // A line should be either a class descriptor, in which case we will dump the complete IMT,
      // or a class descriptor and an interface method, in which case we will lookup the method,
      // determine its IMT slot, and check the class' IMT.
      size_t first_space = line.find(' ');
      if (first_space == std::string::npos) {
        DumpIMTForClass(runtime, line, h_class_loader, &prepared);
      } else {
        DumpIMTForMethod(runtime,
                         line.substr(0, first_space),
                         line.substr(first_space + 1, std::string::npos),
                         h_class_loader,
                         &prepared);
      }
      std::cerr << std::endl;
    }

    return true;
  }

  static bool DumpImtStats(Runtime* runtime,
                           const std::vector<const DexFile*>& dex_files,
                           Handle<mirror::ClassLoader> h_class_loader)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    size_t without_imt = 0;
    size_t with_imt = 0;
    std::map<size_t, size_t> histogram;

    ClassLinker* class_linker = runtime->GetClassLinker();
    const PointerSize pointer_size = class_linker->GetImagePointerSize();
    std::unordered_set<std::string> prepared;

    Thread* self = Thread::Current();
    StackHandleScope<1> scope(self);
    MutableHandle<mirror::Class> h_klass(scope.NewHandle<mirror::Class>(nullptr));

    for (const DexFile* dex_file : dex_files) {
      for (uint32_t class_def_index = 0;
           class_def_index != dex_file->NumClassDefs();
           ++class_def_index) {
        const dex::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
        const char* descriptor = dex_file->GetClassDescriptor(class_def);
        h_klass.Assign(class_linker->FindClass(self, descriptor, h_class_loader));
        if (h_klass == nullptr) {
          std::cerr << "Warning: could not load " << descriptor << std::endl;
          continue;
        }

        if (HasNoIMT(runtime, h_klass, pointer_size, &prepared)) {
          without_imt++;
          continue;
        }

        ImTable* im_table = PrepareAndGetImTable(runtime, h_klass, pointer_size, &prepared);
        if (im_table == nullptr) {
          // Should not happen, but accept.
          without_imt++;
          continue;
        }

        with_imt++;
        for (size_t imt_index = 0; imt_index != ImTable::kSize; ++imt_index) {
          ArtMethod* ptr = im_table->Get(imt_index, pointer_size);
          if (ptr->IsRuntimeMethod()) {
            if (ptr->IsImtUnimplementedMethod()) {
              histogram[0]++;
            } else {
              ImtConflictTable* current_table = ptr->GetImtConflictTable(pointer_size);
              histogram[current_table->NumEntries(pointer_size)]++;
            }
          } else {
            histogram[1]++;
          }
        }
      }
    }

    std::cerr << "IMT stats:"
              << std::endl << std::endl;

    std::cerr << "  " << with_imt << " classes with IMT."
              << std::endl << std::endl;
    std::cerr << "  " << without_imt << " classes without IMT (or copy from Object)."
              << std::endl << std::endl;

    double sum_one = 0;
    size_t count_one = 0;

    std::cerr << "  " << "IMT histogram" << std::endl;
    for (auto& bucket : histogram) {
      std::cerr << "    " << bucket.first << " " << bucket.second << std::endl;
      if (bucket.first > 0) {
        sum_one += bucket.second * bucket.first;
        count_one += bucket.second;
      }
    }

    double count_zero = count_one + histogram[0];
    std::cerr << "   Stats:" << std::endl;
    std::cerr << "     Average depth (including empty): " << (sum_one / count_zero) << std::endl;
    std::cerr << "     Average depth (excluding empty): " << (sum_one / count_one) << std::endl;

    return true;
  }

  // Return whether the given class has no IMT (or the one shared with java.lang.Object).
  static bool HasNoIMT(Runtime* runtime,
                       Handle<mirror::Class> klass,
                       const PointerSize pointer_size,
                       std::unordered_set<std::string>* prepared)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    if (klass->IsObjectClass() || !klass->ShouldHaveImt()) {
      return true;
    }

    if (klass->GetImt(pointer_size) == nullptr) {
      PrepareClass(runtime, klass, prepared);
    }

    ObjPtr<mirror::Class> object_class = GetClassRoot<mirror::Object>();
    DCHECK(object_class->IsObjectClass());

    bool result = klass->GetImt(pointer_size) == object_class->GetImt(pointer_size);

    if (klass->GetIfTable()->Count() == 0) {
      DCHECK(result);
    }

    return result;
  }

  static void PrintTable(ImtConflictTable* table, PointerSize pointer_size)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    if (table == nullptr) {
      std::cerr << "    <No IMT?>" << std::endl;
      return;
    }
    size_t table_index = 0;
    for (;;) {
      ArtMethod* ptr = table->GetInterfaceMethod(table_index, pointer_size);
      if (ptr == nullptr) {
        return;
      }
      table_index++;
      std::cerr << "    " << ptr->PrettyMethod(true) << std::endl;
    }
  }

  static ImTable* PrepareAndGetImTable(Runtime* runtime,
                                       Thread* self,
                                       Handle<mirror::ClassLoader> h_loader,
                                       const std::string& class_name,
                                       const PointerSize pointer_size,
                                       /*out*/ ObjPtr<mirror::Class>* klass_out,
                                       /*inout*/ std::unordered_set<std::string>* prepared)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    if (class_name.empty()) {
      return nullptr;
    }

    std::string descriptor;
    if (class_name[0] == 'L') {
      descriptor = class_name;
    } else {
      descriptor = DotToDescriptor(class_name.c_str());
    }

    ObjPtr<mirror::Class> klass =
        runtime->GetClassLinker()->FindClass(self, descriptor.c_str(), h_loader);

    if (klass == nullptr) {
      self->ClearException();
      std::cerr << "Did not find " <<  class_name << std::endl;
      *klass_out = nullptr;
      return nullptr;
    }

    StackHandleScope<1> scope(Thread::Current());
    Handle<mirror::Class> h_klass = scope.NewHandle<mirror::Class>(klass);

    ImTable* ret = PrepareAndGetImTable(runtime, h_klass, pointer_size, prepared);
    *klass_out = h_klass.Get();
    return ret;
  }

  static ImTable* PrepareAndGetImTable(Runtime* runtime,
                                       Handle<mirror::Class> h_klass,
                                       const PointerSize pointer_size,
                                       /*inout*/ std::unordered_set<std::string>* prepared)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    PrepareClass(runtime, h_klass, prepared);
    return h_klass->GetImt(pointer_size);
  }

  static void DumpIMTForClass(Runtime* runtime,
                              const std::string& class_name,
                              Handle<mirror::ClassLoader> h_loader,
                              std::unordered_set<std::string>* prepared)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    const PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
    ObjPtr<mirror::Class> klass;
    ImTable* imt = PrepareAndGetImTable(runtime,
                                        Thread::Current(),
                                        h_loader,
                                        class_name,
                                        pointer_size,
                                        &klass,
                                        prepared);
    if (imt == nullptr) {
      return;
    }

    std::cerr << class_name << std::endl << " IMT:" << std::endl;
    for (size_t index = 0; index < ImTable::kSize; ++index) {
      std::cerr << "  " << index << ":" << std::endl;
      ArtMethod* ptr = imt->Get(index, pointer_size);
      if (ptr->IsRuntimeMethod()) {
        if (ptr->IsImtUnimplementedMethod()) {
          std::cerr << "    <empty>" << std::endl;
        } else {
          ImtConflictTable* current_table = ptr->GetImtConflictTable(pointer_size);
          PrintTable(current_table, pointer_size);
        }
      } else {
        std::cerr << "    " << ptr->PrettyMethod(true) << std::endl;
      }
    }

    std::cerr << " Interfaces:" << std::endl;
    // Run through iftable, find methods that slot here, see if they fit.
    ObjPtr<mirror::IfTable> if_table = klass->GetIfTable();
    for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
      ObjPtr<mirror::Class> iface = if_table->GetInterface(i);
      std::string iface_name;
      std::cerr << "  " << iface->GetDescriptor(&iface_name) << std::endl;

      for (ArtMethod& iface_method : iface->GetVirtualMethods(pointer_size)) {
        uint32_t class_hash, name_hash, signature_hash;
        ImTable::GetImtHashComponents(&iface_method, &class_hash, &name_hash, &signature_hash);
        uint32_t imt_slot = ImTable::GetImtIndex(&iface_method);
        std::cerr << "    " << iface_method.PrettyMethod(true)
            << " slot=" << imt_slot
            << std::hex
            << " class_hash=0x" << class_hash
            << " name_hash=0x" << name_hash
            << " signature_hash=0x" << signature_hash
            << std::dec
            << std::endl;
      }
    }
  }

  static void DumpIMTForMethod(Runtime* runtime,
                               const std::string& class_name,
                               const std::string& method,
                               Handle<mirror::ClassLoader> h_loader,
                               /*inout*/ std::unordered_set<std::string>* prepared)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    const PointerSize pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
    ObjPtr<mirror::Class> klass;
    ImTable* imt = PrepareAndGetImTable(runtime,
                                        Thread::Current(),
                                        h_loader,
                                        class_name,
                                        pointer_size,
                                        &klass,
                                        prepared);
    if (imt == nullptr) {
      return;
    }

    std::cerr << class_name << " <" << method << ">" << std::endl;
    for (size_t index = 0; index < ImTable::kSize; ++index) {
      ArtMethod* ptr = imt->Get(index, pointer_size);
      if (ptr->IsRuntimeMethod()) {
        if (ptr->IsImtUnimplementedMethod()) {
          continue;
        }

        ImtConflictTable* current_table = ptr->GetImtConflictTable(pointer_size);
        if (current_table == nullptr) {
          continue;
        }

        size_t table_index = 0;
        for (;;) {
          ArtMethod* ptr2 = current_table->GetInterfaceMethod(table_index, pointer_size);
          if (ptr2 == nullptr) {
            break;
          }
          table_index++;

          std::string p_name = ptr2->PrettyMethod(true);
          if (android::base::StartsWith(p_name, method.c_str())) {
            std::cerr << "  Slot "
                      << index
                      << " ("
                      << current_table->NumEntries(pointer_size)
                      << ")"
                      << std::endl;
            PrintTable(current_table, pointer_size);
            return;
          }
        }
      } else {
        std::string p_name = ptr->PrettyMethod(true);
        if (android::base::StartsWith(p_name, method.c_str())) {
          std::cerr << "  Slot " << index << " (1)" << std::endl;
          std::cerr << "    " << p_name << std::endl;
        } else {
          // Run through iftable, find methods that slot here, see if they fit.
          ObjPtr<mirror::IfTable> if_table = klass->GetIfTable();
          for (size_t i = 0, num_interfaces = klass->GetIfTableCount(); i < num_interfaces; ++i) {
            ObjPtr<mirror::Class> iface = if_table->GetInterface(i);
            size_t num_methods = iface->NumDeclaredVirtualMethods();
            if (num_methods > 0) {
              for (ArtMethod& iface_method : iface->GetMethods(pointer_size)) {
                if (ImTable::GetImtIndex(&iface_method) == index) {
                  std::string i_name = iface_method.PrettyMethod(true);
                  if (android::base::StartsWith(i_name, method.c_str())) {
                    std::cerr << "  Slot " << index << " (1)" << std::endl;
                    std::cerr << "    " << p_name << " (" << i_name << ")" << std::endl;
                  }
                }
              }
            }
          }
        }
      }
    }
  }

  // Read lines from the given stream, dropping comments and empty lines
  static std::vector<std::string> ReadCommentedInputStream(std::istream& in_stream) {
    std::vector<std::string> output;
    while (in_stream.good()) {
      std::string dot;
      std::getline(in_stream, dot);
      if (android::base::StartsWith(dot, "#") || dot.empty()) {
        continue;
      }
      output.push_back(dot);
    }
    return output;
  }

  // Read lines from the given file, dropping comments and empty lines.
  static std::vector<std::string> ReadCommentedInputFromFile(const std::string& input_filename) {
    std::unique_ptr<std::ifstream> input_file(new std::ifstream(input_filename, std::ifstream::in));
    if (input_file.get() == nullptr) {
      LOG(ERROR) << "Failed to open input file " << input_filename;
      return std::vector<std::string>();
    }
    std::vector<std::string> result = ReadCommentedInputStream(*input_file);
    input_file->close();
    return result;
  }

  // Prepare a class, i.e., ensure it has a filled IMT. Will do so recursively for superclasses,
  // and note in the given set that the work was done.
  static void PrepareClass(Runtime* runtime,
                           Handle<mirror::Class> h_klass,
                           /*inout*/ std::unordered_set<std::string>* done)
      REQUIRES_SHARED(Locks::mutator_lock_) {
    if (!h_klass->ShouldHaveImt()) {
      return;
    }

    std::string name;
    name = h_klass->GetDescriptor(&name);

    if (done->find(name) != done->end()) {
      return;
    }
    done->insert(name);

    if (h_klass->HasSuperClass()) {
      StackHandleScope<1> h(Thread::Current());
      PrepareClass(runtime, h.NewHandle<mirror::Class>(h_klass->GetSuperClass()), done);
    }

    if (!h_klass->IsTemp()) {
      runtime->GetClassLinker()->FillIMTAndConflictTables(h_klass.Get());
    }
  }
};

struct OatdumpArgs : public CmdlineArgs {
 protected:
  using Base = CmdlineArgs;

  ParseStatus ParseCustom(const char* raw_option,
                          size_t raw_option_length,
                          std::string* error_msg) override {
    DCHECK_EQ(strlen(raw_option), raw_option_length);
    {
      ParseStatus base_parse = Base::ParseCustom(raw_option, raw_option_length, error_msg);
      if (base_parse != kParseUnknownArgument) {
        return base_parse;
      }
    }

    std::string_view option(raw_option, raw_option_length);
    if (StartsWith(option, "--oat-file=")) {
      oat_filename_ = raw_option + strlen("--oat-file=");
    } else if (StartsWith(option, "--dex-file=")) {
      dex_filename_ = raw_option + strlen("--dex-file=");
    } else if (StartsWith(option, "--image=")) {
      image_location_ = raw_option + strlen("--image=");
    } else if (option == "--no-dump:vmap") {
      dump_vmap_ = false;
    } else if (option =="--dump:code_info_stack_maps") {
      dump_code_info_stack_maps_ = true;
    } else if (option == "--no-disassemble") {
      disassemble_code_ = false;
    } else if (option =="--header-only") {
      dump_header_only_ = true;
    } else if (StartsWith(option, "--symbolize=")) {
      oat_filename_ = raw_option + strlen("--symbolize=");
      symbolize_ = true;
    } else if (StartsWith(option, "--only-keep-debug")) {
      only_keep_debug_ = true;
    } else if (StartsWith(option, "--class-filter=")) {
      class_filter_ = raw_option + strlen("--class-filter=");
    } else if (StartsWith(option, "--method-filter=")) {
      method_filter_ = raw_option + strlen("--method-filter=");
    } else if (StartsWith(option, "--list-classes")) {
      list_classes_ = true;
    } else if (StartsWith(option, "--list-methods")) {
      list_methods_ = true;
    } else if (StartsWith(option, "--export-dex-to=")) {
      export_dex_location_ = raw_option + strlen("--export-dex-to=");
    } else if (StartsWith(option, "--addr2instr=")) {
      if (!android::base::ParseUint(raw_option + strlen("--addr2instr="), &addr2instr_)) {
        *error_msg = "Address conversion failed";
        return kParseError;
      }
    } else if (StartsWith(option, "--app-image=")) {
      app_image_ = raw_option + strlen("--app-image=");
    } else if (StartsWith(option, "--app-oat=")) {
      app_oat_ = raw_option + strlen("--app-oat=");
    } else if (StartsWith(option, "--dump-imt=")) {
      imt_dump_ = std::string(option.substr(strlen("--dump-imt=")));
    } else if (option == "--dump-imt-stats") {
      imt_stat_dump_ = true;
    } else {
      return kParseUnknownArgument;
    }

    return kParseOk;
  }

  ParseStatus ParseChecks(std::string* error_msg) override {
    // Infer boot image location from the image location if possible.
    if (boot_image_location_ == nullptr) {
      boot_image_location_ = image_location_;
    }

    // Perform the parent checks.
    ParseStatus parent_checks = Base::ParseChecks(error_msg);
    if (parent_checks != kParseOk) {
      return parent_checks;
    }

    // Perform our own checks.
    if (image_location_ == nullptr && oat_filename_ == nullptr) {
      *error_msg = "Either --image or --oat-file must be specified";
      return kParseError;
    } else if (image_location_ != nullptr && oat_filename_ != nullptr) {
      *error_msg = "Either --image or --oat-file must be specified but not both";
      return kParseError;
    }

    return kParseOk;
  }

  std::string GetUsage() const override {
    std::string usage;

    usage +=
        "Usage: oatdump [options] ...\n"
        "    Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art\n"
        "    Example: adb shell oatdump --image=/system/framework/boot.art\n"
        "\n"
        // Either oat-file or image is required.
        "  --oat-file=<file.oat>: specifies an input oat filename.\n"
        "      Example: --oat-file=/system/framework/arm64/boot.oat\n"
        "\n"
        "  --image=<file.art>: specifies an input image location.\n"
        "      Example: --image=/system/framework/boot.art\n"
        "\n"
        "  --app-image=<file.art>: specifies an input app image. Must also have a specified\n"
        " boot image (with --image) and app oat file (with --app-oat).\n"
        "      Example: --app-image=app.art\n"
        "\n"
        "  --app-oat=<file.odex>: specifies an input app oat.\n"
        "      Example: --app-oat=app.odex\n"
        "\n";

    usage += Base::GetUsage();

    usage +=  // Optional.
        "  --no-dump:vmap may be used to disable vmap dumping.\n"
        "      Example: --no-dump:vmap\n"
        "\n"
        "  --dump:code_info_stack_maps enables dumping of stack maps in CodeInfo sections.\n"
        "      Example: --dump:code_info_stack_maps\n"
        "\n"
        "  --no-disassemble may be used to disable disassembly.\n"
        "      Example: --no-disassemble\n"
        "\n"
        "  --header-only may be used to print only the oat header.\n"
        "      Example: --header-only\n"
        "\n"
        "  --list-classes may be used to list target file classes (can be used with filters).\n"
        "      Example: --list-classes\n"
        "      Example: --list-classes --class-filter=com.example.foo\n"
        "\n"
        "  --list-methods may be used to list target file methods (can be used with filters).\n"
        "      Example: --list-methods\n"
        "      Example: --list-methods --class-filter=com.example --method-filter=foo\n"
        "\n"
        "  --symbolize=<file.oat>: output a copy of file.oat with elf symbols included.\n"
        "      Example: --symbolize=/system/framework/boot.oat\n"
        "\n"
        "  --only-keep-debug<file.oat>: Modifies the behaviour of --symbolize so that\n"
        "      .rodata and .text sections are omitted in the output file to save space.\n"
        "      Example: --symbolize=/system/framework/boot.oat --only-keep-debug\n"
        "\n"
        "  --class-filter=<class name>: only dumps classes that contain the filter.\n"
        "      Example: --class-filter=com.example.foo\n"
        "\n"
        "  --method-filter=<method name>: only dumps methods that contain the filter.\n"
        "      Example: --method-filter=foo\n"
        "\n"
        "  --export-dex-to=<directory>: may be used to export oat embedded dex files.\n"
        "      Example: --export-dex-to=/data/local/tmp\n"
        "\n"
        "  --addr2instr=<address>: output matching method disassembled code from relative\n"
        "                          address (e.g. PC from crash dump)\n"
        "      Example: --addr2instr=0x00001a3b\n"
        "\n"
        "  --dump-imt=<file.txt>: output IMT collisions (if any) for the given receiver\n"
        "                         types and interface methods in the given file. The file\n"
        "                         is read line-wise, where each line should either be a class\n"
        "                         name or descriptor, or a class name/descriptor and a prefix\n"
        "                         of a complete method name (separated by a whitespace).\n"
        "      Example: --dump-imt=imt.txt\n"
        "\n"
        "  --dump-imt-stats: output IMT statistics for the given boot image\n"
        "      Example: --dump-imt-stats"
        "\n";

    return usage;
  }

 public:
  const char* oat_filename_ = nullptr;
  const char* dex_filename_ = nullptr;
  const char* class_filter_ = "";
  const char* method_filter_ = "";
  const char* image_location_ = nullptr;
  std::string elf_filename_prefix_;
  std::string imt_dump_;
  bool dump_vmap_ = true;
  bool dump_code_info_stack_maps_ = false;
  bool disassemble_code_ = true;
  bool symbolize_ = false;
  bool only_keep_debug_ = false;
  bool list_classes_ = false;
  bool list_methods_ = false;
  bool dump_header_only_ = false;
  bool imt_stat_dump_ = false;
  uint32_t addr2instr_ = 0;
  const char* export_dex_location_ = nullptr;
  const char* app_image_ = nullptr;
  const char* app_oat_ = nullptr;
};

struct OatdumpMain : public CmdlineMain<OatdumpArgs> {
  bool NeedsRuntime() override {
    CHECK(args_ != nullptr);

    // If we are only doing the oat file, disable absolute_addresses. Keep them for image dumping.
    bool absolute_addresses = (args_->oat_filename_ == nullptr);

    oat_dumper_options_.reset(new OatDumperOptions(
        args_->dump_vmap_,
        args_->dump_code_info_stack_maps_,
        args_->disassemble_code_,
        absolute_addresses,
        args_->class_filter_,
        args_->method_filter_,
        args_->list_classes_,
        args_->list_methods_,
        args_->dump_header_only_,
        args_->export_dex_location_,
        args_->app_image_,
        args_->app_oat_,
        args_->addr2instr_));

    return (args_->boot_image_location_ != nullptr ||
            args_->image_location_ != nullptr ||
            !args_->imt_dump_.empty()) &&
          !args_->symbolize_;
  }

  bool ExecuteWithoutRuntime() override {
    CHECK(args_ != nullptr);
    CHECK(args_->oat_filename_ != nullptr);

    MemMap::Init();

    if (args_->symbolize_) {
      // ELF has special kind of section called SHT_NOBITS which allows us to create
      // sections which exist but their data is omitted from the ELF file to save space.
      // This is what "strip --only-keep-debug" does when it creates separate ELF file
      // with only debug data. We use it in similar way to exclude .rodata and .text.
      bool no_bits = args_->only_keep_debug_;
      return SymbolizeOat(args_->oat_filename_, args_->dex_filename_, args_->output_name_, no_bits)
          == EXIT_SUCCESS;
    } else {
      return DumpOat(nullptr,
                     args_->oat_filename_,
                     args_->dex_filename_,
                     oat_dumper_options_.get(),
                     args_->os_) == EXIT_SUCCESS;
    }
  }

  bool ExecuteWithRuntime(Runtime* runtime) override {
    CHECK(args_ != nullptr);

    if (!args_->imt_dump_.empty() || args_->imt_stat_dump_) {
      return IMTDumper::Dump(runtime,
                             args_->imt_dump_,
                             args_->imt_stat_dump_,
                             args_->oat_filename_,
                             args_->dex_filename_);
    }

    if (args_->oat_filename_ != nullptr) {
      return DumpOat(runtime,
                     args_->oat_filename_,
                     args_->dex_filename_,
                     oat_dumper_options_.get(),
                     args_->os_) == EXIT_SUCCESS;
    }

    return DumpImages(runtime, oat_dumper_options_.get(), args_->os_) == EXIT_SUCCESS;
  }

  std::unique_ptr<OatDumperOptions> oat_dumper_options_;
};

}  // namespace art

int main(int argc, char** argv) {
  // Output all logging to stderr.
  android::base::SetLogger(android::base::StderrLogger);

  art::OatdumpMain main;
  return main.Main(argc, argv);
}
