oatdump.cc revision 54fc26c7350beb782d042ba61cb06284b3a367e4
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/*
22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project
32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License");
52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License.
62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at
72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *      http://www.apache.org/licenses/LICENSE-2.0
92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes *
102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software
112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and
142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License.
152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */
1678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <stdio.h>
1878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <stdlib.h>
1978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
2027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <fstream>
2127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <iostream>
2278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <string>
2354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe#include <unordered_map>
2478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <vector>
2578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
26e222ee0b794f941af4fb1b32fb8224e32942ea7bElliott Hughes#include "base/stringpiece.h"
27761600567d73b23324ae0251e871c15d6849ffd8Elliott Hughes#include "base/unix_file/fd_file.h"
2878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "class_linker.h"
292dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "class_linker-inl.h"
304f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "dex_file-inl.h"
31e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes#include "dex_instruction.h"
323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers#include "disassembler.h"
3354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe#include "elf_builder.h"
3422d5e735f403c57525fe868304c7123f0ce66399Ian Rogers#include "field_helper.h"
352bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers#include "gc_map.h"
361d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/image_space.h"
371d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/large_object_space.h"
381d54e73444e017d3a65234e0f193846f3e27472bIan Rogers#include "gc/space/space-inl.h"
3978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "image.h"
402bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers#include "indenter.h"
411809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers#include "mapping_table.h"
42ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_field-inl.h"
43ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom#include "mirror/art_method-inl.h"
442dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/array-inl.h"
452dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class-inl.h"
462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object-inl.h"
472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/object_array-inl.h"
48c0a1b18ac71ec0ff3ec0cca3cc8db9eb74e50690Brian Carlstrom#include "noop_compiler_callbacks.h"
49700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom#include "oat.h"
508a630577ed2d9e9571c3434c505e5de223b23c07Vladimir Marko#include "oat_file-inl.h"
51e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes#include "os.h"
5254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe#include "output_stream.h"
5378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "runtime.h"
54a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes#include "safe_map.h"
5500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers#include "scoped_thread_state_change.h"
56c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier#include "thread_list.h"
57ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers#include "verifier/dex_gc_map.h"
582bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers#include "verifier/method_verifier.h"
591809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers#include "vmap_table.h"
6078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
6178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromnamespace art {
6278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
6378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromstatic void usage() {
6478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
6578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "Usage: oatdump [options] ...\n"
669583fbcf597eff6d0b3c5359b8e8d5f70ed82c40Nicolas Geoffray          "    Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art\n"
6729e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "    Example: adb shell oatdump --image=/system/framework/boot.art\n"
6878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "\n");
6978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
70a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "  --oat-file=<file.oat>: specifies an input oat filename.\n"
71a0a2a6c085a6fda2785436663f5c373aa5d43e26TDYa          "      Example: --oat-file=/system/framework/boot.oat\n"
72aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom          "\n");
73aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  fprintf(stderr,
74aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom          "  --image=<file.art>: specifies an input image filename.\n"
7529e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --image=/system/framework/boot.art\n"
76e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
7778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
78e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "  --boot-image=<file.art>: provide the image file for the boot class path.\n"
7929e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --boot-image=/system/framework/boot.art\n"
80e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
81e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  fprintf(stderr,
820f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom          "  --instruction-set=(arm|arm64|mips|x86|x86_64): for locating the image file based on the image location\n"
830f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom          "      set.\n"
840f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom          "      Example: --instruction-set=x86\n"
850f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom          "      Default: %s\n"
860f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom          "\n",
870f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom          GetInstructionSetString(kRuntimeISA));
880f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  fprintf(stderr,
8927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "  --output=<file> may be used to send the output to a file.\n"
9027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "      Example: --output=/tmp/oatdump.txt\n"
9127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "\n");
92404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  fprintf(stderr,
93404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          "  --dump:[raw_mapping_table|raw_gc_map]\n"
94404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          "    Example: --dump:raw_gc_map\n"
95404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          "    Default: neither\n"
96404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          "\n");
9778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  exit(EXIT_FAILURE);
9878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
9978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
100ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogersconst char* image_roots_descriptions_[] = {
1011984651929744dd603fd082e23eacd877b9bc177Ian Rogers  "kResolutionMethod",
10288474b416eb257078e590bf9bc7957cee604a186Jeff Hao  "kImtConflictMethod",
10388474b416eb257078e590bf9bc7957cee604a186Jeff Hao  "kDefaultImt",
104e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kCalleeSaveMethod",
105aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  "kRefsOnlySaveMethod",
106aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  "kRefsAndArgsSaveMethod",
10758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  "kDexCaches",
10834f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom  "kClassRoots",
10978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
11078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
11154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampeclass OatSymbolizer : public CodeOutput {
11254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe public:
11354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  explicit OatSymbolizer(const OatFile* oat_file, std::string& output_name) :
11454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      oat_file_(oat_file), builder_(nullptr), elf_output_(nullptr), output_name_(output_name) {}
11554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
11654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  bool Init() {
11754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    Elf32_Word oat_data_size = oat_file_->GetOatHeader().GetExecutableOffset();
11854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
11954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    uint32_t diff = static_cast<uint32_t>(oat_file_->End() - oat_file_->Begin());
12054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    uint32_t oat_exec_size = diff - oat_data_size;
12154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
12254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (output_name_.empty()) {
12354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      output_name_ = "symbolized.oat";
12454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
12554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    elf_output_ = OS::CreateEmptyFile(output_name_.c_str());
12654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
12754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    builder_.reset(new ElfBuilder<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
12854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                                  Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(
12954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        this,
13054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        elf_output_,
13154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        oat_file_->GetOatHeader().GetInstructionSet(),
13254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        0,
13354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        oat_data_size,
13454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        oat_data_size,
13554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        oat_exec_size,
13654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        true,
13754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        false));
13854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
13954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (!builder_->Init()) {
14054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      builder_.reset(nullptr);
14154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      return false;
14254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
14354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
14454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    return true;
14554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
14654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
14754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  typedef void (OatSymbolizer::*Callback)(const DexFile::ClassDef&,
14854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                                          uint32_t,
14954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                                          const OatFile::OatMethod&,
15054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                                          const DexFile&,
15154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                                          uint32_t,
15254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                                          const DexFile::CodeItem*,
15354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                                          uint32_t);
15454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
15554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  bool Symbolize() {
15654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (builder_.get() == nullptr) {
15754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      return false;
15854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
15954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
16054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    Walk(&art::OatSymbolizer::RegisterForDedup);
16154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
16254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    NormalizeState();
16354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
16454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    Walk(&art::OatSymbolizer::AddSymbol);
16554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
16654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    bool result = builder_->Write();
16754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
16854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    elf_output_->Flush();
16954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    elf_output_->Close();
17054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
17154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    return result;
17254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
17354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
17454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  void Walk(Callback callback) {
17554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file_->GetOatDexFiles();
17654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    for (size_t i = 0; i < oat_dex_files.size(); i++) {
17754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
17854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      CHECK(oat_dex_file != NULL);
17954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      WalkOatDexFile(oat_dex_file, callback);
18054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
18154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
18254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
18354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  void WalkOatDexFile(const OatFile::OatDexFile* oat_dex_file, Callback callback) {
18454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    std::string error_msg;
18554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    std::unique_ptr<const DexFile> dex_file(oat_dex_file->OpenDexFile(&error_msg));
18654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (dex_file.get() == nullptr) {
18754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      return;
18854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
18954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    for (size_t class_def_index = 0;
19054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        class_def_index < dex_file->NumClassDefs();
19154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        class_def_index++) {
19254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
19354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
19454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      OatClassType type = oat_class.GetType();
19554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      switch (type) {
19654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        case kOatClassAllCompiled:
19754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        case kOatClassSomeCompiled:
19854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe          WalkOatClass(oat_class, *dex_file.get(), class_def, callback);
19954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe          break;
20054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
20154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        case kOatClassNoneCompiled:
20254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        case kOatClassMax:
20354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe          // Ignore.
20454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe          break;
20554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      }
20654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
20754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
20854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
20954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  void WalkOatClass(const OatFile::OatClass& oat_class, const DexFile& dex_file,
21054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                    const DexFile::ClassDef& class_def, Callback callback) {
21154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    const byte* class_data = dex_file.GetClassData(class_def);
21254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (class_data == nullptr) {  // empty class such as a marker interface?
21354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      return;
21454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
21554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    // Note: even if this is an interface or a native class, we still have to walk it, as there
21654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    //       might be a static initializer.
21754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    ClassDataItemIterator it(dex_file, class_data);
21854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    SkipAllFields(&it);
21954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    uint32_t class_method_idx = 0;
22054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    while (it.HasNextDirectMethod()) {
22154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_idx);
22254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      WalkOatMethod(class_def, class_method_idx, oat_method, dex_file, it.GetMemberIndex(),
22354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                    it.GetMethodCodeItem(), it.GetMemberAccessFlags(), callback);
22454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      class_method_idx++;
22554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      it.Next();
22654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
22754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    while (it.HasNextVirtualMethod()) {
22854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_idx);
22954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      WalkOatMethod(class_def, class_method_idx, oat_method, dex_file, it.GetMemberIndex(),
23054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                    it.GetMethodCodeItem(), it.GetMemberAccessFlags(), callback);
23154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      class_method_idx++;
23254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      it.Next();
23354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
23454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    DCHECK(!it.HasNext());
23554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
23654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
23754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  void WalkOatMethod(const DexFile::ClassDef& class_def, uint32_t class_method_index,
23854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                     const OatFile::OatMethod& oat_method, const DexFile& dex_file,
23954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                     uint32_t dex_method_idx, const DexFile::CodeItem* code_item,
24054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                     uint32_t method_access_flags, Callback callback) {
24154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if ((method_access_flags & kAccAbstract) != 0) {
24254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      // Abstract method, no code.
24354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      return;
24454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
24554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (oat_method.GetCodeOffset() == 0) {
24654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      // No code.
24754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      return;
24854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
24954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
25054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    (this->*callback)(class_def, class_method_index, oat_method, dex_file, dex_method_idx, code_item,
25154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                      method_access_flags);
25254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
25354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
25454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  void RegisterForDedup(const DexFile::ClassDef& class_def, uint32_t class_method_index,
25554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                        const OatFile::OatMethod& oat_method, const DexFile& dex_file,
25654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                        uint32_t dex_method_idx, const DexFile::CodeItem* code_item,
25754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                        uint32_t method_access_flags) {
25854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    state_[oat_method.GetCodeOffset()]++;
25954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
26054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
26154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  void NormalizeState() {
26254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    for (auto& x : state_) {
26354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      if (x.second == 1) {
26454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        state_[x.first] = 0;
26554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      }
26654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
26754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
26854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
26954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  enum class DedupState {  // private
27054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    kNotDeduplicated,
27154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    kDeduplicatedFirst,
27254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    kDeduplicatedOther
27354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  };
27454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  DedupState IsDuplicated(uint32_t offset) {
27554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (state_[offset] == 0) {
27654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      return DedupState::kNotDeduplicated;
27754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
27854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (state_[offset] == 1) {
27954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      return DedupState::kDeduplicatedOther;
28054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
28154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    state_[offset] = 1;
28254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    return DedupState::kDeduplicatedFirst;
28354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
28454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
28554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  void AddSymbol(const DexFile::ClassDef& class_def, uint32_t class_method_index,
28654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                 const OatFile::OatMethod& oat_method, const DexFile& dex_file,
28754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                 uint32_t dex_method_idx, const DexFile::CodeItem* code_item,
28854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                 uint32_t method_access_flags) {
28954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    DedupState dedup = IsDuplicated(oat_method.GetCodeOffset());
29054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (dedup != DedupState::kDeduplicatedOther) {
29154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      std::string pretty_name = PrettyMethod(dex_method_idx, dex_file, true);
29254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
29354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      if (dedup == DedupState::kDeduplicatedFirst) {
29454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        pretty_name = "[Dedup]" + pretty_name;
29554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      }
29654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
29754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      ElfSymtabBuilder<Elf32_Word, Elf32_Sword, Elf32_Addr,
29854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      Elf32_Sym, Elf32_Shdr>* symtab = &builder_->symtab_builder_;
29954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
30054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      symtab->AddSymbol(pretty_name, &builder_->text_builder_, oat_method.GetCodeOffset() -
30154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                        oat_file_->GetOatHeader().GetExecutableOffset(), true,
30254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                        oat_method.GetQuickCodeSize(), STB_GLOBAL, STT_FUNC);
30354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
30454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
30554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
30654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  // Write oat code. Required by ElfBuilder/CodeOutput.
30754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  bool Write(OutputStream* out) {
30854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    return out->WriteFully(oat_file_->Begin(), oat_file_->End() - oat_file_->Begin());
30954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
31054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
31154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe private:
31254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  static void SkipAllFields(ClassDataItemIterator* it) {
31354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    while (it->HasNextStaticField()) {
31454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      it->Next();
31554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
31654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    while (it->HasNextInstanceField()) {
31754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      it->Next();
31854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
31954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  }
32054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
32154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  const OatFile* oat_file_;
32254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  std::unique_ptr<ElfBuilder<Elf32_Word, Elf32_Sword, Elf32_Addr, Elf32_Dyn,
32354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe                              Elf32_Sym, Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr> > builder_;
32454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  File* elf_output_;
32554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  std::unordered_map<uint32_t, uint32_t> state_;
32654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  std::string output_name_;
32754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe};
32854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe
329e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughesclass OatDumper {
330aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom public:
3319583fbcf597eff6d0b3c5359b8e8d5f70ed82c40Nicolas Geoffray  explicit OatDumper(const OatFile& oat_file, bool dump_raw_mapping_table, bool dump_raw_gc_map)
3329583fbcf597eff6d0b3c5359b8e8d5f70ed82c40Nicolas Geoffray    : oat_file_(oat_file),
333a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes      oat_dex_files_(oat_file.GetOatDexFiles()),
334404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison      dump_raw_mapping_table_(dump_raw_mapping_table),
335404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison      dump_raw_gc_map_(dump_raw_gc_map),
336a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes      disassembler_(Disassembler::Create(oat_file_.GetOatHeader().GetInstructionSet())) {
3373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    AddAllOffsets();
3383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
3393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
3403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void Dump(std::ostream& os) {
3413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    const OatHeader& oat_header = oat_file_.GetOatHeader();
342aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
343aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "MAGIC:\n";
344aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetMagic() << "\n\n";
345aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
346aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "CHECKSUM:\n";
347ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("0x%08x\n\n", oat_header.GetChecksum());
348aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
349a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes    os << "INSTRUCTION SET:\n";
350a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes    os << oat_header.GetInstructionSet() << "\n\n";
351a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes
3527020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison    os << "INSTRUCTION SET FEATURES:\n";
3537020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison    os << oat_header.GetInstructionSetFeatures().GetFeatureString() << "\n\n";
3547020278bce98a0735dc6abcbd33bdf1ed2634f1dDave Allison
355aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "DEX FILE COUNT:\n";
356aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetDexFileCount() << "\n\n";
357aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
3582ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom#define DUMP_OAT_HEADER_OFFSET(label, offset) \
3592ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    os << label " OFFSET:\n"; \
3602ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    os << StringPrintf("0x%08x", oat_header.offset()); \
3612ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    if (oat_header.offset() != 0) { \
3622ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom      os << StringPrintf(" (%p)", oat_file_.Begin() + oat_header.offset()); \
3632ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    } \
3642ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    os << StringPrintf("\n\n");
3652ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom
3662ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("EXECUTABLE", GetExecutableOffset);
3672ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("INTERPRETER TO INTERPRETER BRIDGE",
3682ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetInterpreterToInterpreterBridgeOffset);
3692ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("INTERPRETER TO COMPILED CODE BRIDGE",
3702ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetInterpreterToCompiledCodeBridgeOffset);
3712ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("JNI DLSYM LOOKUP",
3722ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetJniDlsymLookupOffset);
3732ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("PORTABLE IMT CONFLICT TRAMPOLINE",
3742ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetPortableImtConflictTrampolineOffset);
3752ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("PORTABLE RESOLUTION TRAMPOLINE",
3762ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetPortableResolutionTrampolineOffset);
3772ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("PORTABLE TO INTERPRETER BRIDGE",
3782ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetPortableToInterpreterBridgeOffset);
3792ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("QUICK GENERIC JNI TRAMPOLINE",
3802ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetQuickGenericJniTrampolineOffset);
3812ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("QUICK IMT CONFLICT TRAMPOLINE",
3822ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetQuickImtConflictTrampolineOffset);
3832ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("QUICK RESOLUTION TRAMPOLINE",
3842ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetQuickResolutionTrampolineOffset);
3852ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    DUMP_OAT_HEADER_OFFSET("QUICK TO INTERPRETER BRIDGE",
3862ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           GetQuickToInterpreterBridgeOffset);
3872ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom#undef DUMP_OAT_HEADER_OFFSET
388aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
389a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    os << "IMAGE PATCH DELTA:\n" << oat_header.GetImagePatchDelta();
390a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
39128db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom    os << "IMAGE FILE LOCATION OAT CHECKSUM:\n";
39228db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatChecksum());
39328db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom
39428db0129e5d7ef642cf8845c86c0e11832817085Brian Carlstrom    os << "IMAGE FILE LOCATION OAT BEGIN:\n";
395700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationOatDataBegin());
39681f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
39722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    // Print the key-value store.
39822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    {
39922f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      os << "KEY VALUE STORE:\n";
40022f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      size_t index = 0;
40122f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      const char* key;
40222f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      const char* value;
40322f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      while (oat_header.GetStoreKeyValuePairByIndex(index, &key, &value)) {
40422f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        os << key << " = " << value << "\n";
40522f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe        index++;
40622f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      }
40722f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe      os << "\n";
40822f8e5c82d12951be38cd893426e13bee33fd69dAndreas Gampe    }
40981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
41030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "BEGIN:\n";
4113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << reinterpret_cast<const void*>(oat_file_.Begin()) << "\n\n";
412aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
41330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "END:\n";
4143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << reinterpret_cast<const void*>(oat_file_.End()) << "\n\n";
415aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
416aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
417aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
4183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
4193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
4203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      CHECK(oat_dex_file != NULL);
4213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOatDexFile(os, *oat_dex_file);
4223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
4233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
4243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
4253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  size_t ComputeSize(const void* oat_data) {
4263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (reinterpret_cast<const byte*>(oat_data) < oat_file_.Begin() ||
4273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        reinterpret_cast<const byte*>(oat_data) > oat_file_.End()) {
4283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return 0;  // Address not in oat file
4293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
430ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    uintptr_t begin_offset = reinterpret_cast<uintptr_t>(oat_data) -
431ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                             reinterpret_cast<uintptr_t>(oat_file_.Begin());
432ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    auto it = offsets_.upper_bound(begin_offset);
4333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    CHECK(it != offsets_.end());
434ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    uintptr_t end_offset = *it;
4353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return end_offset - begin_offset;
4363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
437e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
438f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  InstructionSet GetInstructionSet() {
439f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    return oat_file_.GetOatHeader().GetInstructionSet();
440f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
441f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
442ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  const void* GetQuickOatCode(mirror::ArtMethod* m) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
4433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
4443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
4458d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      CHECK(oat_dex_file != nullptr);
4468d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      std::string error_msg;
447700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers      std::unique_ptr<const DexFile> dex_file(oat_dex_file->OpenDexFile(&error_msg));
4488d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      if (dex_file.get() == nullptr) {
4498d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers        LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation()
4508d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers            << "': " << error_msg;
4518d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      } else {
4528b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers        const DexFile::ClassDef* class_def =
453bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier            dex_file->FindClassDef(m->GetDeclaringClassDescriptor());
4548b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers        if (class_def != NULL) {
4558b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers          uint16_t class_def_index = dex_file->GetIndexForClassDef(*class_def);
456d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko          const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
4573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          size_t method_index = m->GetMethodIndex();
458d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko          return oat_class.GetOatMethod(method_index).GetQuickCode();
4593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
4603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
461aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
4623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return NULL;
463aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
464aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
465aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom private:
4663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void AddAllOffsets() {
467e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // We don't know the length of the code for each method, but we need to know where to stop
468e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // when disassembling. What we do know is that a region of code will be followed by some other
469e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // region, so if we keep a sorted sequence of the start of each region, we can infer the length
470e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // of a piece of code by using upper_bound to find the start of the next region.
4713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
4723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
473e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      CHECK(oat_dex_file != NULL);
4748d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      std::string error_msg;
475700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers      std::unique_ptr<const DexFile> dex_file(oat_dex_file->OpenDexFile(&error_msg));
4768d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      if (dex_file.get() == nullptr) {
4778d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers        LOG(WARNING) << "Failed to open dex file '" << oat_dex_file->GetDexFileLocation()
4788d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers            << "': " << error_msg;
4793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        continue;
480e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
481ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      offsets_.insert(reinterpret_cast<uintptr_t>(&dex_file->GetHeader()));
4822ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom      for (size_t class_def_index = 0;
4832ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom           class_def_index < dex_file->NumClassDefs();
4842ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom           class_def_index++) {
485e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
486d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko        const OatFile::OatClass oat_class = oat_dex_file->GetOatClass(class_def_index);
487e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        const byte* class_data = dex_file->GetClassData(class_def);
488e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        if (class_data != NULL) {
489e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          ClassDataItemIterator it(*dex_file, class_data);
490e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          SkipAllFields(it);
491e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          uint32_t class_method_index = 0;
492e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          while (it.HasNextDirectMethod()) {
493d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko            AddOffsets(oat_class.GetOatMethod(class_method_index++));
494e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            it.Next();
495e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          }
496e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          while (it.HasNextVirtualMethod()) {
497d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko            AddOffsets(oat_class.GetOatMethod(class_method_index++));
498e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            it.Next();
499e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          }
500e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        }
501e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
502e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
503e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
504e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // If the last thing in the file is code for a method, there won't be an offset for the "next"
505e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // thing. Instead of having a special case in the upper_bound code, let's just add an entry
506e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // for the end of the file.
507ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    offsets_.insert(oat_file_.Size());
508e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
509e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
510e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  void AddOffsets(const OatFile::OatMethod& oat_method) {
51195ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    uint32_t code_offset = oat_method.GetCodeOffset();
51295ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    if (oat_file_.GetOatHeader().GetInstructionSet() == kThumb2) {
51395ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom      code_offset &= ~0x1;
51495ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    }
51595ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    offsets_.insert(code_offset);
516e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    offsets_.insert(oat_method.GetMappingTableOffset());
517e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    offsets_.insert(oat_method.GetVmapTableOffset());
5180c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers    offsets_.insert(oat_method.GetNativeGcMapOffset());
519e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
520e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
5213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpOatDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) {
522aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "OAT DEX FILE:\n";
523a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str());
524ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("checksum: 0x%08x\n", oat_dex_file.GetDexFileLocationChecksum());
525590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
526590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    // Create the verifier early.
527590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
5288d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    std::string error_msg;
529700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers    std::unique_ptr<const DexFile> dex_file(oat_dex_file.OpenDexFile(&error_msg));
530a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    if (dex_file.get() == NULL) {
5318d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      os << "NOT FOUND: " << error_msg << "\n\n";
532aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return;
533aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
5342ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    for (size_t class_def_index = 0;
5352ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom         class_def_index < dex_file->NumClassDefs();
5362ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom         class_def_index++) {
537aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
538aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const char* descriptor = dex_file->GetClassDescriptor(class_def);
539d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko      const OatFile::OatClass oat_class = oat_dex_file.GetOatClass(class_def_index);
540ba150c37d582eeeb8c11ba5245edc281cf31793cBrian Carlstrom      os << StringPrintf("%zd: %s (type_idx=%d)", class_def_index, descriptor, class_def.class_idx_)
541d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko         << " (" << oat_class.GetStatus() << ")"
542d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko         << " (" << oat_class.GetType() << ")\n";
543d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko      // TODO: include bitmap here if type is kOatClassSomeCompiled?
5442bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
5452bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      std::ostream indented_os(&indent_filter);
546d3c5bebcb52a67cb06e7ab303eaf45f230c08b60Vladimir Marko      DumpOatClass(indented_os, oat_class, *(dex_file.get()), class_def);
547aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
548aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
549aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
550aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
551aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
552e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  static void SkipAllFields(ClassDataItemIterator& it) {
5530571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextStaticField()) {
5540571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
555aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
5560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextInstanceField()) {
5570571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
558aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
559e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
560aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
5613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpOatClass(std::ostream& os, const OatFile::OatClass& oat_class, const DexFile& dex_file,
5623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                    const DexFile::ClassDef& class_def) {
563e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    const byte* class_data = dex_file.GetClassData(class_def);
564e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    if (class_data == NULL) {  // empty class such as a marker interface?
565e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      return;
566e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
567e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    ClassDataItemIterator it(dex_file, class_data);
568e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    SkipAllFields(it);
5692bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    uint32_t class_method_idx = 0;
5700571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextDirectMethod()) {
5712bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_idx);
5728b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers      DumpOatMethod(os, class_def, class_method_idx, oat_method, dex_file,
5732bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                    it.GetMemberIndex(), it.GetMethodCodeItem(), it.GetMemberAccessFlags());
5742bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      class_method_idx++;
5750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
576aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
5770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextVirtualMethod()) {
5782bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_idx);
5798b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers      DumpOatMethod(os, class_def, class_method_idx, oat_method, dex_file,
5802bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                    it.GetMemberIndex(), it.GetMethodCodeItem(), it.GetMemberAccessFlags());
5812bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      class_method_idx++;
5820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
583aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
5840571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    DCHECK(!it.HasNext());
585aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
586aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
587e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
5888b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers  void DumpOatMethod(std::ostream& os, const DexFile::ClassDef& class_def,
5898b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers                     uint32_t class_method_index,
590e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes                     const OatFile::OatMethod& oat_method, const DexFile& dex_file,
5912bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                     uint32_t dex_method_idx, const DexFile::CodeItem* code_item,
5922bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                     uint32_t method_access_flags) {
5932bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << StringPrintf("%d: %s (dex_method_idx=%d)\n",
594db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers                       class_method_index, PrettyMethod(dex_method_idx, dex_file, true).c_str(),
595db7bdc1086c44fe628b6743f98d7d85a5c03343aIan Rogers                       dex_method_idx);
5962bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    Indenter indent1_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
597a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe    std::unique_ptr<std::ostream> indent1_os(new std::ostream(&indent1_filter));
598a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe    Indenter indent2_filter(indent1_os->rdbuf(), kIndentChar, kIndentBy1Count);
599a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe    std::unique_ptr<std::ostream> indent2_os(new std::ostream(&indent2_filter));
6002bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    {
601a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent1_os << "DEX CODE:\n";
602a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      DumpDexCode(*indent2_os, dex_file, code_item);
6032bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
6042bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    if (Runtime::Current() != NULL) {
605a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent1_os << "VERIFIER TYPE ANALYSIS:\n";
606a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      DumpVerifier(*indent2_os, dex_method_idx, &dex_file, class_def, code_item,
6078b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers                   method_access_flags);
6082bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
6092bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    {
610a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent1_os << "OAT DATA:\n";
611a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe
612a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("frame_size_in_bytes: %zd\n", oat_method.GetFrameSizeInBytes());
613a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("core_spill_mask: 0x%08x ", oat_method.GetCoreSpillMask());
614a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      DumpSpillMask(*indent2_os, oat_method.GetCoreSpillMask(), false);
615a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("\nfp_spill_mask: 0x%08x ", oat_method.GetFpSpillMask());
616a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      DumpSpillMask(*indent2_os, oat_method.GetFpSpillMask(), true);
617a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("\nvmap_table: %p (offset=0x%08x)\n",
618a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe                                  oat_method.GetVmapTable(), oat_method.GetVmapTableOffset());
619a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      DumpVmap(*indent2_os, oat_method);
620faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      DumpVregLocations(*indent2_os, oat_method, code_item);
621a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("mapping_table: %p (offset=0x%08x)\n",
622a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe                                  oat_method.GetMappingTable(), oat_method.GetMappingTableOffset());
623404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison      if (dump_raw_mapping_table_) {
624a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe        Indenter indent3_filter(indent2_os->rdbuf(), kIndentChar, kIndentBy1Count);
6252bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        std::ostream indent3_os(&indent3_filter);
6262bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        DumpMappingTable(indent3_os, oat_method);
6272bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
628a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("gc_map: %p (offset=0x%08x)\n",
629a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe                                  oat_method.GetNativeGcMap(), oat_method.GetNativeGcMapOffset());
630404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison      if (dump_raw_gc_map_) {
631a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe        Indenter indent3_filter(indent2_os->rdbuf(), kIndentChar, kIndentBy1Count);
6322bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        std::ostream indent3_os(&indent3_filter);
6332bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        DumpGcMap(indent3_os, oat_method, code_item);
6342bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
6352bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
6362bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    {
637ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const void* code = oat_method.GetQuickCode();
638ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      uint32_t code_size = oat_method.GetQuickCodeSize();
639ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if (code == nullptr) {
640ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        code = oat_method.GetPortableCode();
641ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        code_size = oat_method.GetPortableCodeSize();
642ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      }
643a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent1_os << StringPrintf("CODE: %p (offset=0x%08x size=%d)%s\n",
644ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                                 code,
6452bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                 oat_method.GetCodeOffset(),
646ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                                 code_size,
647ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                                 code != nullptr ? "..." : "");
648590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
649590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      Runtime* runtime = Runtime::Current();
650590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      if (runtime != nullptr) {
651590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        ScopedObjectAccess soa(Thread::Current());
652bf99f77dda749e2b653e8c45259b1fb56e7bb012Mathieu Chartier        StackHandleScope<1> hs(soa.Self());
653eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier        Handle<mirror::DexCache> dex_cache(
654eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier            hs.NewHandle(runtime->GetClassLinker()->FindDexCache(dex_file)));
655bf99f77dda749e2b653e8c45259b1fb56e7bb012Mathieu Chartier        verifier::MethodVerifier verifier(&dex_file, dex_cache, NullHandle<mirror::ClassLoader>(),
656bf99f77dda749e2b653e8c45259b1fb56e7bb012Mathieu Chartier                                          &class_def, code_item, dex_method_idx,
657bf99f77dda749e2b653e8c45259b1fb56e7bb012Mathieu Chartier                                          NullHandle<mirror::ArtMethod>(), method_access_flags,
65846960fe5dcc1be07b39a55114338423a73554449Ian Rogers                                          true, true, true);
659590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier        verifier.Verify();
660a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe        DumpCode(*indent2_os, &verifier, oat_method, code_item);
661590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      } else {
662a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe        DumpCode(*indent2_os, nullptr, oat_method, code_item);
663590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier      }
6642bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
6653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
6663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
6673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpSpillMask(std::ostream& os, uint32_t spill_mask, bool is_float) {
6683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (spill_mask == 0) {
6693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
6703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
6712bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "(";
6723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < 32; i++) {
6733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if ((spill_mask & (1 << i)) != 0) {
6743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (is_float) {
6753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << "fr" << i;
6763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        } else {
6773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << "r" << i;
6783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
6793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        spill_mask ^= 1 << i;  // clear bit
6803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (spill_mask != 0) {
6813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << ", ";
6823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        } else {
6833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          break;
6843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
6853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
6863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
6873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << ")";
6883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
6893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
690b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpVmap(std::ostream& os, const OatFile::OatMethod& oat_method) {
6911809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    const uint8_t* raw_table = oat_method.GetVmapTable();
6921809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    if (raw_table != NULL) {
6931809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      const VmapTable vmap_table(raw_table);
6941809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      bool first = true;
6951809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      bool processing_fp = false;
6961809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      uint32_t spill_mask = oat_method.GetCoreSpillMask();
6971809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      for (size_t i = 0; i < vmap_table.Size(); i++) {
6981809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        uint16_t dex_reg = vmap_table[i];
6991809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        uint32_t cpu_reg = vmap_table.ComputeRegister(spill_mask, i,
7001809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers                                                      processing_fp ? kFloatVReg : kIntVReg);
7011809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << (first ? "v" : ", v")  << dex_reg;
7021809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        if (!processing_fp) {
7031809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          os << "/r" << cpu_reg;
7041809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        } else {
7051809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          os << "/fr" << cpu_reg;
7061809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
7071809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        first = false;
7081809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        if (!processing_fp && dex_reg == 0xFFFF) {
7091809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          processing_fp = true;
7101809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          spill_mask = oat_method.GetFpSpillMask();
7111809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
7123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
7131809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      os << "\n";
7143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
7153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
7163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
717faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru  void DumpVregLocations(std::ostream& os, const OatFile::OatMethod& oat_method,
718faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru                         const DexFile::CodeItem* code_item) {
719faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru    if (code_item != nullptr) {
720faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      size_t num_locals_ins = code_item->registers_size_;
721faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      size_t num_ins = code_item->ins_size_;
722faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      size_t num_locals = num_locals_ins - num_ins;
723faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      size_t num_outs = code_item->outs_size_;
724faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
725faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      os << "vr_stack_locations:";
726faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      for (size_t reg = 0; reg <= num_locals_ins; reg++) {
727faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        // For readability, delimit the different kinds of VRs.
728faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        if (reg == num_locals_ins) {
729faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru          os << "\n\tmethod*:";
730faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        } else if (reg == num_locals && num_ins > 0) {
731faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru          os << "\n\tins:";
732faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        } else if (reg == 0 && num_locals > 0) {
733faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru          os << "\n\tlocals:";
734faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        }
735faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
736faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        uint32_t offset = StackVisitor::GetVRegOffset(code_item, oat_method.GetCoreSpillMask(),
737faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru                                                      oat_method.GetFpSpillMask(),
738faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru                                                      oat_method.GetFrameSizeInBytes(), reg,
739faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru                                                      GetInstructionSet());
740faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        os << " v" << reg << "[sp + #" << offset << "]";
741faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      }
742faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
743faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      for (size_t out_reg = 0; out_reg < num_outs; out_reg++) {
744faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        if (out_reg == 0) {
745faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru          os << "\n\touts:";
746faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        }
747faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
748faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        uint32_t offset = StackVisitor::GetOutVROffset(out_reg, GetInstructionSet());
749faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        os << " v" << out_reg << "[sp + #" << offset << "]";
750faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      }
751faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
752faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      os << "\n";
753faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru    }
754faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru  }
755faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
756b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DescribeVReg(std::ostream& os, const OatFile::OatMethod& oat_method,
7572bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                    const DexFile::CodeItem* code_item, size_t reg, VRegKind kind) {
7581809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    const uint8_t* raw_table = oat_method.GetVmapTable();
759b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (raw_table != NULL) {
760b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      const VmapTable vmap_table(raw_table);
761b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      uint32_t vmap_offset;
7621809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      if (vmap_table.IsInContext(reg, kind, &vmap_offset)) {
7632bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
7642bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        uint32_t spill_mask = is_float ? oat_method.GetFpSpillMask()
7652bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                       : oat_method.GetCoreSpillMask();
7662bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << (is_float ? "fr" : "r") << vmap_table.ComputeRegister(spill_mask, vmap_offset, kind);
767b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      } else {
768b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        uint32_t offset = StackVisitor::GetVRegOffset(code_item, oat_method.GetCoreSpillMask(),
769b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                                                      oat_method.GetFpSpillMask(),
77042fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray                                                      oat_method.GetFrameSizeInBytes(), reg,
77142fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray                                                      GetInstructionSet());
772b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        os << "[sp + #" << offset << "]";
773b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
774b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    }
775b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
776b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers
777ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void DumpGcMapRegisters(std::ostream& os, const OatFile::OatMethod& oat_method,
778ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                          const DexFile::CodeItem* code_item,
779ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                          size_t num_regs, const uint8_t* reg_bitmap) {
780ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    bool first = true;
781ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    for (size_t reg = 0; reg < num_regs; reg++) {
782ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) {
783ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        if (first) {
784ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          os << "  v" << reg << " (";
785ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
786ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          os << ")";
787ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          first = false;
788ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        } else {
789ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          os << ", v" << reg << " (";
790ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
791ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          os << ")";
792ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        }
793ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      }
794ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
795ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (first) {
796ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      os << "No registers in GC map\n";
797ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else {
798ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      os << "\n";
799ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
800ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  }
801b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpGcMap(std::ostream& os, const OatFile::OatMethod& oat_method,
802b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                 const DexFile::CodeItem* code_item) {
803b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint8_t* gc_map_raw = oat_method.GetNativeGcMap();
804ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (gc_map_raw == nullptr) {
805ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      return;  // No GC map.
8063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
807ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* quick_code = oat_method.GetQuickCode();
808ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (quick_code != nullptr) {
809ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      NativePcOffsetToReferenceMap map(gc_map_raw);
810ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      for (size_t entry = 0; entry < map.NumEntries(); entry++) {
811ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(quick_code) +
812ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            map.GetNativePcOffset(entry);
813ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        os << StringPrintf("%p", native_pc);
814ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DumpGcMapRegisters(os, oat_method, code_item, map.RegWidth() * 8, map.GetBitMap(entry));
815ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      }
816ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else {
817ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const void* portable_code = oat_method.GetPortableCode();
818ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      CHECK(portable_code != nullptr);
819ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      verifier::DexPcToReferenceMap map(gc_map_raw);
820ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      for (size_t entry = 0; entry < map.NumEntries(); entry++) {
821ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        uint32_t dex_pc = map.GetDexPc(entry);
822ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        os << StringPrintf("0x%08x", dex_pc);
823ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DumpGcMapRegisters(os, oat_method, code_item, map.RegWidth() * 8, map.GetBitMap(entry));
8243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
8253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
826aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
827e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
8283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpMappingTable(std::ostream& os, const OatFile::OatMethod& oat_method) {
829ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* quick_code = oat_method.GetQuickCode();
830ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (quick_code == nullptr) {
8312bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      return;
8322bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
8331809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    MappingTable table(oat_method.GetMappingTable());
8341809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    if (table.TotalSize() != 0) {
8351809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
8361809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      std::ostream indent_os(&indent_filter);
8371809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      if (table.PcToDexSize() != 0) {
8381809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        typedef MappingTable::PcToDexIterator It;
8391809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << "suspend point mappings {\n";
8401809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
8411809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          indent_os << StringPrintf("0x%04x -> 0x%04x\n", cur.NativePcOffset(), cur.DexPc());
8421809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
8431809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << "}\n";
8441809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      }
8451809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      if (table.DexToPcSize() != 0) {
8461809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        typedef MappingTable::DexToPcIterator It;
8471809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << "catch entry mappings {\n";
8481809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        for (It cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
8491809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          indent_os << StringPrintf("0x%04x -> 0x%04x\n", cur.NativePcOffset(), cur.DexPc());
8501809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
8511809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << "}\n";
8523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
8533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
8543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
8553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
8561809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers  uint32_t DumpMappingAtOffset(std::ostream& os, const OatFile::OatMethod& oat_method,
8571809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers                               size_t offset, bool suspend_point_mapping) {
8581809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    MappingTable table(oat_method.GetMappingTable());
8591809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    if (suspend_point_mapping && table.PcToDexSize() > 0) {
8601809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      typedef MappingTable::PcToDexIterator It;
8611809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
8621809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        if (offset == cur.NativePcOffset()) {
8634b8c13ee44c4c959d7b8de9adff7ce6df48c31d0Brian Carlstrom          os << StringPrintf("suspend point dex PC: 0x%04x\n", cur.DexPc());
8641809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          return cur.DexPc();
8651809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
866b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
8671809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    } else if (!suspend_point_mapping && table.DexToPcSize() > 0) {
8681809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      typedef MappingTable::DexToPcIterator It;
8691809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      for (It cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
8701809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        if (offset == cur.NativePcOffset()) {
8714b8c13ee44c4c959d7b8de9adff7ce6df48c31d0Brian Carlstrom          os << StringPrintf("catch entry dex PC: 0x%04x\n", cur.DexPc());
8721809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          return cur.DexPc();
873b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
874b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
8753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
8762bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    return DexFile::kDexNoIndex;
877b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
8783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
8792bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers  void DumpGcMapAtNativePcOffset(std::ostream& os, const OatFile::OatMethod& oat_method,
8802bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                 const DexFile::CodeItem* code_item, size_t native_pc_offset) {
881b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint8_t* gc_map_raw = oat_method.GetNativeGcMap();
882b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (gc_map_raw != NULL) {
883b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      NativePcOffsetToReferenceMap map(gc_map_raw);
8842bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      if (map.HasEntry(native_pc_offset)) {
885b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        size_t num_regs = map.RegWidth() * 8;
8862bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        const uint8_t* reg_bitmap = map.FindBitMap(native_pc_offset);
887b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        bool first = true;
888b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        for (size_t reg = 0; reg < num_regs; reg++) {
889b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) {
890b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            if (first) {
8912bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              os << "GC map objects:  v" << reg << " (";
8922bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
893b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << ")";
894b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              first = false;
895b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            } else {
896b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << ", v" << reg << " (";
8972bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
898b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << ")";
899b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            }
900b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          }
901b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
902b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        if (!first) {
903b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          os << "\n";
904b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
905b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
9063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
907b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
9083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
909590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  void DumpVRegsAtDexPc(std::ostream& os, verifier::MethodVerifier* verifier,
910590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier                        const OatFile::OatMethod& oat_method,
911590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier                        const DexFile::CodeItem* code_item, uint32_t dex_pc) {
912590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    DCHECK(verifier != nullptr);
9137b3ddd27c223fcce784314f78fda7f67dcb37730Ian Rogers    std::vector<int32_t> kinds = verifier->DescribeVRegs(dex_pc);
9142bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    bool first = true;
9152bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    for (size_t reg = 0; reg < code_item->registers_size_; reg++) {
9162bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
9172bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      if (kind != kUndefined) {
9182bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        if (first) {
9192bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          os << "VRegs:  v";
9202bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          first = false;
9212bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        } else {
9222bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          os << ", v";
9232bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        }
9242bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << reg << " (";
9252bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        switch (kind) {
9262bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          case kImpreciseConstant:
9272bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            os << "Imprecise Constant: " << kinds.at((reg * 2) + 1) << ", ";
9282bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            DescribeVReg(os, oat_method, code_item, reg, kind);
9292bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            break;
9302bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          case kConstant:
9312bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            os << "Constant: " << kinds.at((reg * 2) + 1);
9322bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            break;
9332bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          default:
9342bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            DescribeVReg(os, oat_method, code_item, reg, kind);
9352bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            break;
9362bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        }
9372bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << ")";
9382bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
9392bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
9402bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    if (!first) {
9412bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "\n";
9422bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
9432bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers  }
9442bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
9452bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
946b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpDexCode(std::ostream& os, const DexFile& dex_file, const DexFile::CodeItem* code_item) {
947b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    if (code_item != NULL) {
948b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      size_t i = 0;
949b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      while (i < code_item->insns_size_in_code_units_) {
950b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        const Instruction* instruction = Instruction::At(&code_item->insns_[i]);
9512bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("0x%04zx: %s\n", i, instruction->DumpString(&dex_file).c_str());
952b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        i += instruction->SizeInCodeUnits();
953e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
954e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
955b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
956b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers
9572bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers  void DumpVerifier(std::ostream& os, uint32_t dex_method_idx, const DexFile* dex_file,
9588b2c0b9abc3f520495f4387ea040132ba85cae69Ian Rogers                    const DexFile::ClassDef& class_def, const DexFile::CodeItem* code_item,
9592bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                    uint32_t method_access_flags) {
9602bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    if ((method_access_flags & kAccNative) == 0) {
9612bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      ScopedObjectAccess soa(Thread::Current());
962bf99f77dda749e2b653e8c45259b1fb56e7bb012Mathieu Chartier      StackHandleScope<1> hs(soa.Self());
963eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      Handle<mirror::DexCache> dex_cache(
964eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier          hs.NewHandle(Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file)));
9652bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      verifier::MethodVerifier::VerifyMethodAndDump(os, dex_method_idx, dex_file, dex_cache,
966bf99f77dda749e2b653e8c45259b1fb56e7bb012Mathieu Chartier                                                    NullHandle<mirror::ClassLoader>(), &class_def,
967bf99f77dda749e2b653e8c45259b1fb56e7bb012Mathieu Chartier                                                    code_item, NullHandle<mirror::ArtMethod>(),
9682bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                                    method_access_flags);
9692bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
9702bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers  }
9712bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
972590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  void DumpCode(std::ostream& os, verifier::MethodVerifier* verifier,
973590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier                const OatFile::OatMethod& oat_method, const DexFile::CodeItem* code_item) {
974ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* portable_code = oat_method.GetPortableCode();
975ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* quick_code = oat_method.GetQuickCode();
976ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
977ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    size_t code_size = oat_method.GetQuickCodeSize();
978ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if ((code_size == 0) || ((portable_code == nullptr) && (quick_code == nullptr))) {
9792bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "NO CODE!\n";
980b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      return;
981ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else if (quick_code != nullptr) {
982ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
983ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      size_t offset = 0;
984ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      while (offset < code_size) {
985ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DumpMappingAtOffset(os, oat_method, offset, false);
986ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        offset += disassembler_->Dump(os, quick_native_pc + offset);
987ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        uint32_t dex_pc = DumpMappingAtOffset(os, oat_method, offset, true);
988ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        if (dex_pc != DexFile::kDexNoIndex) {
989ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          DumpGcMapAtNativePcOffset(os, oat_method, code_item, offset);
990ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          if (verifier != nullptr) {
991ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            DumpVRegsAtDexPc(os, verifier, oat_method, code_item, dex_pc);
992ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          }
9932bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        }
9942bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
995ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else {
996ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      CHECK(portable_code != nullptr);
997ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      CHECK_EQ(code_size, 0U);  // TODO: disassembly of portable is currently not supported.
998b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    }
999b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
1000b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers
10013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const OatFile& oat_file_;
10023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  std::vector<const OatFile::OatDexFile*> oat_dex_files_;
1003404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_mapping_table_;
1004404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_gc_map_;
1005ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  std::set<uintptr_t> offsets_;
1006700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<Disassembler> disassembler_;
1007aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom};
1008aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
10093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogersclass ImageDumper {
101027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom public:
10112ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom  explicit ImageDumper(std::ostream* os, gc::space::ImageSpace& image_space,
1012404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison                       const ImageHeader& image_header, bool dump_raw_mapping_table,
1013404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison                       bool dump_raw_gc_map)
10142ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom      : os_(os), image_space_(image_space), image_header_(image_header),
1015404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        dump_raw_mapping_table_(dump_raw_mapping_table),
1016404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        dump_raw_gc_map_(dump_raw_gc_map) {}
101727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
1018b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers  void Dump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
10192bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    std::ostream& os = *os_;
10202bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "MAGIC: " << image_header_.GetMagic() << "\n\n";
10212bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
10222bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "IMAGE BEGIN: " << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n";
10232bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
102431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    os << "IMAGE BITMAP OFFSET: " << reinterpret_cast<void*>(image_header_.GetImageBitmapOffset())
102531e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier       << " SIZE: " << reinterpret_cast<void*>(image_header_.GetImageBitmapSize()) << "\n\n";
102631e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
10272bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "OAT CHECKSUM: " << StringPrintf("0x%08x\n\n", image_header_.GetOatChecksum());
10282bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
1029700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    os << "OAT FILE BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatFileBegin()) << "\n\n";
10302bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
1031700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    os << "OAT DATA BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatDataBegin()) << "\n\n";
1032700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
1033700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    os << "OAT DATA END:" << reinterpret_cast<void*>(image_header_.GetOatDataEnd()) << "\n\n";
1034700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
1035700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    os << "OAT FILE END:" << reinterpret_cast<void*>(image_header_.GetOatFileEnd()) << "\n\n";
10362bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
1037a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    os << "PATCH DELTA:" << image_header_.GetPatchDelta() << "\n\n";
1038a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
10392bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    {
10402bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n";
10412bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      Indenter indent1_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
10422bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      std::ostream indent1_os(&indent1_filter);
10432bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax));
10442bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
10452bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
10462bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        const char* image_root_description = image_roots_descriptions_[i];
10472dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers        mirror::Object* image_root_object = image_header_.GetImageRoot(image_root);
10482bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        indent1_os << StringPrintf("%s: %p\n", image_root_description, image_root_object);
10492bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        if (image_root_object->IsObjectArray()) {
10502bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          Indenter indent2_filter(indent1_os.rdbuf(), kIndentChar, kIndentBy1Count);
10512bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          std::ostream indent2_os(&indent2_filter);
10522dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers          mirror::ObjectArray<mirror::Object>* image_root_object_array
1053fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              = image_root_object->AsObjectArray<mirror::Object>();
10542bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          for (int i = 0; i < image_root_object_array->GetLength(); i++) {
10552dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers            mirror::Object* value = image_root_object_array->Get(i);
1056fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            size_t run = 0;
1057fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            for (int32_t j = i + 1; j < image_root_object_array->GetLength(); j++) {
1058fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              if (value == image_root_object_array->Get(j)) {
1059fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers                run++;
1060fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              } else {
1061fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers                break;
1062fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              }
1063fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            }
1064fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            if (run == 0) {
1065fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              indent2_os << StringPrintf("%d: ", i);
1066fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            } else {
1067fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              indent2_os << StringPrintf("%d to %zd: ", i, i + run);
1068fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              i = i + run;
1069fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            }
10702bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            if (value != NULL) {
10712bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              PrettyObjectValue(indent2_os, value->GetClass(), value);
10722bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            } else {
10732bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              indent2_os << i << ": null\n";
10742bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            }
1075d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
107634f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        }
107734f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      }
107827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    }
10792bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "\n";
108027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
1081aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
10822ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    std::string image_filename = image_space_.GetImageFilename();
10832ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(image_filename);
10842bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "OAT LOCATION: " << oat_location;
10852bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "\n";
10868d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    std::string error_msg;
1087a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    const OatFile* oat_file = class_linker->FindOpenedOatFileFromOatLocation(oat_location);
1088a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    if (oat_file == nullptr) {
1089a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light      oat_file = OatFile::Open(oat_location, oat_location, NULL, false, &error_msg);
1090a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light      if (oat_file == nullptr) {
1091a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light        os << "NOT FOUND: " << error_msg << "\n";
1092a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light        return;
1093a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light      }
1094aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
10952bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "\n";
1096aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
10973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.oat_file_bytes = oat_file->Size();
109878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
10999583fbcf597eff6d0b3c5359b8e8d5f70ed82c40Nicolas Geoffray    oat_dumper_.reset(new OatDumper(*oat_file, dump_raw_mapping_table_,
1100404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        dump_raw_gc_map_));
11013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
110202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    for (const OatFile::OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) {
110305f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers      CHECK(oat_dex_file != NULL);
110402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      stats_.oat_dex_file_sizes.push_back(std::make_pair(oat_dex_file->GetDexFileLocation(),
110502e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                                                         oat_dex_file->FileSize()));
110605f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers    }
110705f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers
11082bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "OBJECTS:\n" << std::flush;
1109b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier
1110b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    // Loop through all the image spaces and dump their objects.
11111d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    gc::Heap* heap = Runtime::Current()->GetHeap();
11121d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    const std::vector<gc::space::ContinuousSpace*>& spaces = heap->GetContinuousSpaces();
111350b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    Thread* self = Thread::Current();
1114357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    {
1115c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier      {
1116c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
1117c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        heap->FlushAllocStack();
1118c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier      }
111990d706849a09590f150748ff97256ef718aca441Hiroshi Yamauchi      // Since FlushAllocStack() above resets the (active) allocation
112090d706849a09590f150748ff97256ef718aca441Hiroshi Yamauchi      // stack. Need to revoke the thread-local allocation stacks that
112190d706849a09590f150748ff97256ef718aca441Hiroshi Yamauchi      // point into it.
1122c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier      {
1123c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        self->TransitionFromRunnableToSuspended(kNative);
1124c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        ThreadList* thread_list = Runtime::Current()->GetThreadList();
1125c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        thread_list->SuspendAll();
1126c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        heap->RevokeAllThreadLocalAllocationStacks(self);
1127c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        thread_list->ResumeAll();
1128c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        self->TransitionFromSuspendedToRunnable();
1129c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier      }
1130357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    }
11312bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    {
11322bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      std::ostream* saved_os = os_;
11332bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
11342bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      std::ostream indent_os(&indent_filter);
11352bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os_ = &indent_os;
11362bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
113702e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      for (const auto& space : spaces) {
11382bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        if (space->IsImageSpace()) {
11391d54e73444e017d3a65234e0f193846f3e27472bIan Rogers          gc::space::ImageSpace* image_space = space->AsImageSpace();
11402bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          image_space->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
11412bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          indent_os << "\n";
11422bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        }
11432fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier      }
11442bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      // Dump the large objects separately.
1145bbd695c71e0bf518f582e84524e1cdeb3de3896cMathieu Chartier      heap->GetLargeObjectsSpace()->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
11462bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      indent_os << "\n";
11472bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os_ = saved_os;
1148b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    }
11492bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "STATS:\n" << std::flush;
1150700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers    std::unique_ptr<File> file(OS::OpenFileForReading(image_filename.c_str()));
11516f277751ec5bfc0d7469b2cc7f7134e9032593f1Brian Carlstrom    if (file.get() == NULL) {
11522ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom      LOG(WARNING) << "Failed to find image in " << image_filename;
11536f277751ec5bfc0d7469b2cc7f7134e9032593f1Brian Carlstrom    }
11546f277751ec5bfc0d7469b2cc7f7134e9032593f1Brian Carlstrom    if (file.get() != NULL) {
11552ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom      stats_.file_bytes = file->GetLength();
11566f277751ec5bfc0d7469b2cc7f7134e9032593f1Brian Carlstrom    }
11573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t header_bytes = sizeof(ImageHeader);
11583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.header_bytes = header_bytes;
11593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t alignment_bytes = RoundUp(header_bytes, kObjectAlignment) - header_bytes;
11603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.alignment_bytes += alignment_bytes;
116132327098e300ab66671b891a18bf669576fc896aMathieu Chartier    stats_.alignment_bytes += image_header_.GetImageBitmapOffset() - image_header_.GetImageSize();
116232327098e300ab66671b891a18bf669576fc896aMathieu Chartier    stats_.bitmap_bytes += image_header_.GetImageBitmapSize();
11632bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    stats_.Dump(os);
11642bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "\n";
116527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
11662bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << std::flush;
11673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
11682bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    oat_dumper_->Dump(os);
11693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
1170d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
11713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers private:
11722dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static void PrettyObjectValue(std::ostream& os, mirror::Class* type, mirror::Object* value)
1173b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1174d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    CHECK(type != NULL);
1175d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (value == NULL) {
11762bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("null   %s\n", PrettyDescriptor(type).c_str());
1177d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsStringClass()) {
11782dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::String* string = value->AsString();
11792bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   String: %s\n", string,
118068b56858367e29461ae290fd797443a1ef6d8005Ian Rogers                         PrintableString(string->ToModifiedUtf8().c_str()).c_str());
118164b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (type->IsClassClass()) {
11822dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Class* klass = value->AsClass();
11832bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   Class: %s\n", klass, PrettyDescriptor(klass).c_str());
1184ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (type->IsArtFieldClass()) {
1185ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtField* field = value->AsArtField();
11862bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   Field: %s\n", field, PrettyField(field).c_str());
1187ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (type->IsArtMethodClass()) {
1188ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtMethod* method = value->AsArtMethod();
11892bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   Method: %s\n", method, PrettyMethod(method).c_str());
1190d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
11912bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   %s\n", value, PrettyDescriptor(type).c_str());
1192d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
1193d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
1194d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
1195ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  static void PrintField(std::ostream& os, mirror::ArtField* field, mirror::Object* obj)
1196b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
119761c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    const char* descriptor = field->GetTypeDescriptor();
119861c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    os << StringPrintf("%s: ", field->GetName());
119948efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers    if (descriptor[0] != 'L' && descriptor[0] != '[') {
120061c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier      StackHandleScope<1> hs(Thread::Current());
120161c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier      FieldHelper fh(hs.NewHandle(field));
12022dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Class* type = fh.GetType();
120337f05ef45e0393de812d51261dc293240c17294dFred Shih      DCHECK(type->IsPrimitive());
120448efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      if (type->IsPrimitiveLong()) {
1205ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        os << StringPrintf("%" PRId64 " (0x%" PRIx64 ")\n", field->Get64(obj), field->Get64(obj));
120648efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else if (type->IsPrimitiveDouble()) {
12072bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj));
120848efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else if (type->IsPrimitiveFloat()) {
12092bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%f (%a)\n", field->GetFloat(obj), field->GetFloat(obj));
121037f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveInt()) {
12112bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%d (0x%x)\n", field->Get32(obj), field->Get32(obj));
121237f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveChar()) {
121337f05ef45e0393de812d51261dc293240c17294dFred Shih        os << StringPrintf("%u (0x%x)\n", field->GetChar(obj), field->GetChar(obj));
121437f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveShort()) {
121537f05ef45e0393de812d51261dc293240c17294dFred Shih        os << StringPrintf("%d (0x%x)\n", field->GetShort(obj), field->GetShort(obj));
121637f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveBoolean()) {
121737f05ef45e0393de812d51261dc293240c17294dFred Shih        os << StringPrintf("%s (0x%x)\n", field->GetBoolean(obj)? "true" : "false",
121837f05ef45e0393de812d51261dc293240c17294dFred Shih            field->GetBoolean(obj));
121937f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveByte()) {
122037f05ef45e0393de812d51261dc293240c17294dFred Shih        os << StringPrintf("%d (0x%x)\n", field->GetByte(obj), field->GetByte(obj));
122137f05ef45e0393de812d51261dc293240c17294dFred Shih      } else {
122237f05ef45e0393de812d51261dc293240c17294dFred Shih        LOG(FATAL) << "Unknown type: " << PrettyClass(type);
122348efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      }
1224d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
122548efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      // Get the value, don't compute the type unless it is non-null as we don't want
122648efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      // to cause class loading.
12272dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Object* value = field->GetObj(obj);
122848efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      if (value == NULL) {
12292bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("null   %s\n", PrettyDescriptor(descriptor).c_str());
123048efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else {
123150239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers        // Grab the field type without causing resolution.
123261c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier        StackHandleScope<1> hs(Thread::Current());
123361c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier        FieldHelper fh(hs.NewHandle(field));
123450239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers        mirror::Class* field_type = fh.GetType(false);
123550239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers        if (field_type != NULL) {
123650239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers          PrettyObjectValue(os, field_type, value);
123750239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers        } else {
123850239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers          os << StringPrintf("%p   %s\n", value, PrettyDescriptor(descriptor).c_str());
123950239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers        }
124048efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      }
1241d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
1242d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
1243d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
12442dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static void DumpFields(std::ostream& os, mirror::Object* obj, mirror::Class* klass)
1245b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
12462dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* super = klass->GetSuperClass();
1247d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (super != NULL) {
12482bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      DumpFields(os, obj, super);
1249d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
1250ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields();
1251d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (fields != NULL) {
1252d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < fields->GetLength(); i++) {
1253ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom        mirror::ArtField* field = fields->Get(i);
12542bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        PrintField(os, field, obj);
1255d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
1256d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
1257d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
1258d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
12592dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  bool InDumpSpace(const mirror::Object* object) {
12603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return image_space_.Contains(object);
1261f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
12623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1263ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  const void* GetQuickOatCodeBegin(mirror::ArtMethod* m)
1264b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1265ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* quick_code = m->GetEntryPointFromQuickCompiledCode();
126698d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    if (quick_code == Runtime::Current()->GetClassLinker()->GetQuickResolutionTrampoline()) {
1267ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      quick_code = oat_dumper_->GetQuickOatCode(m);
12683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
1269f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    if (oat_dumper_->GetInstructionSet() == kThumb2) {
1270ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      quick_code = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(quick_code) & ~0x1);
1271f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
1272ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return quick_code;
12733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
12743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1275ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  uint32_t GetQuickOatCodeSize(mirror::ArtMethod* m)
1276b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1277ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetQuickOatCodeBegin(m));
1278ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (oat_code_begin == nullptr) {
1279f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom      return 0;
1280f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
1281f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    return oat_code_begin[-1];
1282f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
1283f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
1284ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  const void* GetQuickOatCodeEnd(mirror::ArtMethod* m)
1285b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1286ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetQuickOatCodeBegin(m));
1287f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    if (oat_code_begin == NULL) {
1288f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom      return NULL;
1289f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
1290ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return oat_code_begin + GetQuickOatCodeSize(m);
1291f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
1292f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
12932dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static void Callback(mirror::Object* obj, void* arg)
1294b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
129578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(obj != NULL);
129678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(arg != NULL);
12973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    ImageDumper* state = reinterpret_cast<ImageDumper*>(arg);
129878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    if (!state->InDumpSpace(obj)) {
129978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      return;
130078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
1301916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1302916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes = obj->SizeOf();
1303916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
1304916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.object_bytes += object_bytes;
1305916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.alignment_bytes += alignment_bytes;
1306916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
13072bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    std::ostream& os = *state->os_;
13082dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* obj_class = obj->GetClass();
1309d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj_class->IsArrayClass()) {
13102bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p: %s length:%d\n", obj, PrettyDescriptor(obj_class).c_str(),
13112bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         obj->AsArray()->GetLength());
1312d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
13132dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Class* klass = obj->AsClass();
13142bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p: java.lang.Class \"%s\" (", obj, PrettyDescriptor(klass).c_str())
13152bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers         << klass->GetStatus() << ")\n";
1316ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (obj->IsArtField()) {
13174b8c13ee44c4c959d7b8de9adff7ce6df48c31d0Brian Carlstrom      os << StringPrintf("%p: java.lang.reflect.ArtField %s\n", obj,
1318ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                         PrettyField(obj->AsArtField()).c_str());
1319ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (obj->IsArtMethod()) {
13204b8c13ee44c4c959d7b8de9adff7ce6df48c31d0Brian Carlstrom      os << StringPrintf("%p: java.lang.reflect.ArtMethod %s\n", obj,
1321ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                         PrettyMethod(obj->AsArtMethod()).c_str());
1322d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj_class->IsStringClass()) {
13232bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p: java.lang.String %s\n", obj,
132468b56858367e29461ae290fd797443a1ef6d8005Ian Rogers                         PrintableString(obj->AsString()->ToModifiedUtf8().c_str()).c_str());
132578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
13262bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p: %s\n", obj, PrettyDescriptor(obj_class).c_str());
132778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
13282bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
13292bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    std::ostream indent_os(&indent_filter);
13302bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    DumpFields(indent_os, obj, obj_class);
1331d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj->IsObjectArray()) {
13322dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::ObjectArray<mirror::Object>* obj_array = obj->AsObjectArray<mirror::Object>();
1333d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      int32_t length = obj_array->GetLength();
1334d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < length; i++) {
13352dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers        mirror::Object* value = obj_array->Get(i);
1336d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        size_t run = 0;
1337d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t j = i + 1; j < length; j++) {
1338d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          if (value == obj_array->Get(j)) {
1339d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            run++;
1340d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          } else {
1341d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            break;
1342d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
1343d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
1344d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        if (run == 0) {
13452bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          indent_os << StringPrintf("%d: ", i);
134678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        } else {
13472bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          indent_os << StringPrintf("%d to %zd: ", i, i + run);
1348d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          i = i + run;
134978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        }
13502ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom        mirror::Class* value_class =
13512ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom            (value == NULL) ? obj_class->GetComponentType() : value->GetClass();
13522bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        PrettyObjectValue(indent_os, value_class, value);
1353d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
1354d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
1355ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ObjectArray<mirror::ArtField>* sfields = obj->AsClass()->GetSFields();
1356d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      if (sfields != NULL) {
13572bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        indent_os << "STATICS:\n";
13582bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        Indenter indent2_filter(indent_os.rdbuf(), kIndentChar, kIndentBy1Count);
13592bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        std::ostream indent2_os(&indent2_filter);
1360d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t i = 0; i < sfields->GetLength(); i++) {
1361ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom          mirror::ArtField* field = sfields->Get(i);
13622bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          PrintField(indent2_os, field, field->GetDeclaringClass());
1363d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
1364d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
1365ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (obj->IsArtMethod()) {
1366ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtMethod* method = obj->AsArtMethod();
1367d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      if (method->IsNative()) {
1368ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        // TODO: portable dumping.
1369ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DCHECK(method->GetNativeGcMap() == nullptr) << PrettyMethod(method);
1370ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DCHECK(method->GetMappingTable() == nullptr) << PrettyMethod(method);
13713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first_occurrence;
1372ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        const void* quick_oat_code = state->GetQuickOatCodeBegin(method);
1373ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
1374ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        state->ComputeOatSize(quick_oat_code, &first_occurrence);
13753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurrence) {
1376ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          state->stats_.native_to_managed_code_bytes += quick_oat_code_size;
13773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
1378ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        if (quick_oat_code != method->GetEntryPointFromQuickCompiledCode()) {
1379ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          indent_os << StringPrintf("OAT CODE: %p\n", quick_oat_code);
13803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
13811984651929744dd603fd082e23eacd877b9bc177Ian Rogers      } else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
138288474b416eb257078e590bf9bc7957cee604a186Jeff Hao          method->IsResolutionMethod() || method->IsImtConflictMethod() ||
1383bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier          method->IsClassInitializer()) {
13840c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers        DCHECK(method->GetNativeGcMap() == NULL) << PrettyMethod(method);
13853320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
1386916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      } else {
1387bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        const DexFile::CodeItem* code_item = method->GetCodeItem();
1388d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
1389916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        state->stats_.dex_instruction_bytes += dex_instruction_bytes;
1390e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
1391a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        bool first_occurrence;
13920c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers        size_t gc_map_bytes = state->ComputeOatSize(method->GetNativeGcMap(), &first_occurrence);
1393a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
13943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.gc_map_bytes += gc_map_bytes;
13953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
13963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
13973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t pc_mapping_table_bytes =
13981809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers            state->ComputeOatSize(method->GetMappingTable(), &first_occurrence);
1399a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
14003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
14013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
14023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
14033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t vmap_table_bytes =
14041809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers            state->ComputeOatSize(method->GetVmapTable(), &first_occurrence);
1405a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
14063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.vmap_table_bytes += vmap_table_bytes;
14073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
14083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1409ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        // TODO: portable dumping.
1410ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        const void* quick_oat_code_begin = state->GetQuickOatCodeBegin(method);
1411ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        const void* quick_oat_code_end = state->GetQuickOatCodeEnd(method);
1412ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
1413ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        state->ComputeOatSize(quick_oat_code_begin, &first_occurrence);
1414a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
1415ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          state->stats_.managed_code_bytes += quick_oat_code_size;
14160d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          if (method->IsConstructor()) {
14170d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            if (method->IsStatic()) {
1418ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers              state->stats_.class_initializer_code_bytes += quick_oat_code_size;
14190d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            } else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
1420ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers              state->stats_.large_initializer_code_bytes += quick_oat_code_size;
14210d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            }
14220d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          } else if (dex_instruction_bytes > kLargeMethodDexBytes) {
1423ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            state->stats_.large_method_code_bytes += quick_oat_code_size;
14240d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          }
14253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
1426ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        state->stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size;
14273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1428ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        indent_os << StringPrintf("OAT CODE: %p-%p\n", quick_oat_code_begin, quick_oat_code_end);
14292bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        indent_os << StringPrintf("SIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n",
14302bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes);
14313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
14323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t total_size = dex_instruction_bytes + gc_map_bytes + pc_mapping_table_bytes +
1433ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            vmap_table_bytes + quick_oat_code_size + object_bytes;
14343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
14353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double expansion =
1436ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            static_cast<double>(quick_oat_code_size) / static_cast<double>(dex_instruction_bytes);
14373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        state->stats_.ComputeOutliers(total_size, expansion, method);
143878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      }
143978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
14401ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    std::string temp;
14411ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    state->stats_.Update(obj_class->GetDescriptor(&temp), object_bytes);
144278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
144327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
14443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  std::set<const void*> already_seen_;
14453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  // Compute the size of the given data within the oat file and whether this is the first time
14463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  // this data has been requested
1447a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  size_t ComputeOatSize(const void* oat_data, bool* first_occurrence) {
14483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (already_seen_.count(oat_data) == 0) {
1449a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      *first_occurrence = true;
14503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      already_seen_.insert(oat_data);
14513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    } else {
1452a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      *first_occurrence = false;
14533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
14543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return oat_dumper_->ComputeSize(oat_data);
145527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  }
1456916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1457916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom public:
1458916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  struct Stats {
14593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t oat_file_bytes;
1460916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t file_bytes;
1461916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1462916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t header_bytes;
1463916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes;
146432327098e300ab66671b891a18bf669576fc896aMathieu Chartier    size_t bitmap_bytes;
1465916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes;
1466916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1467916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_code_bytes;
14683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t managed_code_bytes_ignoring_deduplication;
1469916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_to_native_code_bytes;
1470916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t native_to_managed_code_bytes;
14710d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    size_t class_initializer_code_bytes;
14720d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    size_t large_initializer_code_bytes;
14730d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    size_t large_method_code_bytes;
1474916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
14753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t gc_map_bytes;
1476916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t pc_mapping_table_bytes;
14773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t vmap_table_bytes;
1478916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1479916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t dex_instruction_bytes;
1480916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1481ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    std::vector<mirror::ArtMethod*> method_outlier;
14823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::vector<size_t> method_outlier_size;
14833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::vector<double> method_outlier_expansion;
1484700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers    std::vector<std::pair<std::string, size_t>> oat_dex_file_sizes;
14853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
14863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    explicit Stats()
14873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        : oat_file_bytes(0),
14883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          file_bytes(0),
1489916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          header_bytes(0),
1490916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          object_bytes(0),
149132327098e300ab66671b891a18bf669576fc896aMathieu Chartier          bitmap_bytes(0),
1492916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          alignment_bytes(0),
1493916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_code_bytes(0),
14943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          managed_code_bytes_ignoring_deduplication(0),
1495916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_to_native_code_bytes(0),
1496916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          native_to_managed_code_bytes(0),
14970d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          class_initializer_code_bytes(0),
14980d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          large_initializer_code_bytes(0),
14990d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          large_method_code_bytes(0),
15003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          gc_map_bytes(0),
1501916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          pc_mapping_table_bytes(0),
15023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          vmap_table_bytes(0),
1503916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          dex_instruction_bytes(0) {}
1504916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1505a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    struct SizeAndCount {
1506a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      SizeAndCount(size_t bytes, size_t count) : bytes(bytes), count(count) {}
1507a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      size_t bytes;
1508a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      size_t count;
1509a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    };
1510a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable;
1511a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    SizeAndCountTable sizes_and_counts;
1512a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
1513fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogers    void Update(const char* descriptor, size_t object_bytes) {
1514a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor);
1515a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      if (it != sizes_and_counts.end()) {
1516a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        it->second.bytes += object_bytes;
1517a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        it->second.count += 1;
1518a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      } else {
1519a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        sizes_and_counts.Put(descriptor, SizeAndCount(object_bytes, 1));
1520a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      }
1521a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    }
1522916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
15233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    double PercentOfOatBytes(size_t size) {
15243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100;
15253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
15263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1527916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfFileBytes(size_t size) {
1528916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
1529916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1530916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1531916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfObjectBytes(size_t size) {
1532916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
1533916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1534916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1535ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    void ComputeOutliers(size_t total_size, double expansion, mirror::ArtMethod* method) {
15363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier_size.push_back(total_size);
15373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier_expansion.push_back(expansion);
15383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier.push_back(method);
15393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
15403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
154100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    void DumpOutliers(std::ostream& os)
1542b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
15433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_sizes = 0;
15443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_sizes_squared = 0;
15453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_expansion = 0;
15463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_expansion_squared = 0;
15473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t n = method_outlier_size.size();
15483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 0; i < n; i++) {
15493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t cur_size = method_outlier_size[i];
15503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_sizes += cur_size;
15513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_sizes_squared += cur_size * cur_size;
15523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double cur_expansion = method_outlier_expansion[i];
15533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_expansion += cur_expansion;
15543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_expansion_squared += cur_expansion * cur_expansion;
15553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
15563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t size_mean = sum_of_sizes / n;
15573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t size_variance = (sum_of_sizes_squared - sum_of_sizes * size_mean) / (n - 1);
15583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      double expansion_mean = sum_of_expansion / n;
15593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      double expansion_variance =
15603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          (sum_of_expansion_squared - sum_of_expansion * expansion_mean) / (n - 1);
15613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
15623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      // Dump methods whose size is a certain number of standard deviations from the mean
15633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t dumped_values = 0;
15643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t skipped_values = 0;
15653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 100; i > 0; i--) {  // i is the current number of standard deviations
15663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t cur_size_variance = i * i * size_variance;
15673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first = true;
15683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        for (size_t j = 0; j < n; j++) {
15693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          size_t cur_size = method_outlier_size[j];
15703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (cur_size > size_mean) {
15713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            size_t cur_var = cur_size - size_mean;
15723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            cur_var = cur_var * cur_var;
15733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            if (cur_var > cur_size_variance) {
15743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              if (dumped_values > 20) {
15753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (i == 1) {
15763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  skipped_values++;
15773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                } else {
15783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  i = 2;  // jump to counting for 1 standard deviation
15793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  break;
15803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
15813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              } else {
15823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (first) {
1583c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                  os << "\nBig methods (size > " << i << " standard deviations the norm):\n";
15843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  first = false;
15853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
15862bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                os << PrettyMethod(method_outlier[j]) << " requires storage of "
1587c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                    << PrettySize(cur_size) << "\n";
15883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                method_outlier_size[j] = 0;  // don't consider this method again
15893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                dumped_values++;
15903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              }
15913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            }
15923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
15933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
15943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
15953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (skipped_values > 0) {
15962bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << "... skipped " << skipped_values
1597c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes           << " methods with size > 1 standard deviation from the norm\n";
15983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
1599c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << std::flush;
16003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
16013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      // Dump methods whose expansion is a certain number of standard deviations from the mean
16023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      dumped_values = 0;
16033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      skipped_values = 0;
16043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 10; i > 0; i--) {  // i is the current number of standard deviations
16053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double cur_expansion_variance = i * i * expansion_variance;
16063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first = true;
16073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        for (size_t j = 0; j < n; j++) {
16083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          double cur_expansion = method_outlier_expansion[j];
16093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (cur_expansion > expansion_mean) {
16103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            size_t cur_var = cur_expansion - expansion_mean;
16113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            cur_var = cur_var * cur_var;
16123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            if (cur_var > cur_expansion_variance) {
16133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              if (dumped_values > 20) {
16143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (i == 1) {
16153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  skipped_values++;
16163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                } else {
16173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  i = 2;  // jump to counting for 1 standard deviation
16183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  break;
16193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
16203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              } else {
16213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (first) {
16223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  os << "\nLarge expansion methods (size > " << i
1623c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                      << " standard deviations the norm):\n";
16243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  first = false;
16253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
16262bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                os << PrettyMethod(method_outlier[j]) << " expanded code by "
1627c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                   << cur_expansion << "\n";
16283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                method_outlier_expansion[j] = 0.0;  // don't consider this method again
16293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                dumped_values++;
16303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              }
16313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            }
16323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
16333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
16343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
16353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (skipped_values > 0) {
16362bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << "... skipped " << skipped_values
1637c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes           << " methods with expansion > 1 standard deviation from the norm\n";
16383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
1639c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << "\n" << std::flush;
16403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
16413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1642b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
16432bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      {
16442bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << "art_file_bytes = " << PrettySize(file_bytes) << "\n\n"
16452bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers           << "art_file_bytes = header_bytes + object_bytes + alignment_bytes\n";
16462bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
16472bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        std::ostream indent_os(&indent_filter);
16482bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        indent_os << StringPrintf("header_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
16492bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  "object_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
165032327098e300ab66671b891a18bf669576fc896aMathieu Chartier                                  "bitmap_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
16512bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  "alignment_bytes =  %8zd (%2.0f%% of art file bytes)\n\n",
16522bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  header_bytes, PercentOfFileBytes(header_bytes),
16532bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  object_bytes, PercentOfFileBytes(object_bytes),
165432327098e300ab66671b891a18bf669576fc896aMathieu Chartier                                  bitmap_bytes, PercentOfFileBytes(bitmap_bytes),
16552bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  alignment_bytes, PercentOfFileBytes(alignment_bytes))
16562bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            << std::flush;
165732327098e300ab66671b891a18bf669576fc896aMathieu Chartier        CHECK_EQ(file_bytes, bitmap_bytes + header_bytes + object_bytes + alignment_bytes);
16582bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
1659916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
16602bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "object_bytes breakdown:\n";
1661916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      size_t object_bytes_total = 0;
166202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      for (const auto& sizes_and_count : sizes_and_counts) {
166302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier        const std::string& descriptor(sizes_and_count.first);
166402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier        double average = static_cast<double>(sizes_and_count.second.bytes) /
166502e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier            static_cast<double>(sizes_and_count.second.count);
166602e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier        double percent = PercentOfObjectBytes(sizes_and_count.second.bytes);
16672bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%32s %8zd bytes %6zd instances "
1668a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes                           "(%4.0f bytes/instance) %2.0f%% of object_bytes\n",
166902e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                           descriptor.c_str(), sizes_and_count.second.bytes,
167002e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                           sizes_and_count.second.count, average, percent);
167102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier        object_bytes_total += sizes_and_count.second.bytes;
1672916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      }
1673c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << "\n" << std::flush;
1674916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(object_bytes, object_bytes_total);
1675916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
16762bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("oat_file_bytes               = %8zd\n"
16772bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "managed_code_bytes           = %8zd (%2.0f%% of oat file bytes)\n"
16782bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "managed_to_native_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
16792bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "native_to_managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n\n"
16802bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "class_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
16812bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "large_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
16822bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "large_method_code_bytes      = %8zd (%2.0f%% of oat file bytes)\n\n",
168305f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers                         oat_file_bytes,
16842ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         managed_code_bytes,
16852ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(managed_code_bytes),
16862ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         managed_to_native_code_bytes,
16872ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(managed_to_native_code_bytes),
16882ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         native_to_managed_code_bytes,
16892ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(native_to_managed_code_bytes),
16902ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         class_initializer_code_bytes,
16912ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(class_initializer_code_bytes),
16922ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         large_initializer_code_bytes,
16932ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(large_initializer_code_bytes),
16942ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         large_method_code_bytes,
16952ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(large_method_code_bytes))
16962bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            << "DexFile sizes:\n";
169702e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      for (const std::pair<std::string, size_t>& oat_dex_file_size : oat_dex_file_sizes) {
16982bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%s = %zd (%2.0f%% of oat file bytes)\n",
169902e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                           oat_dex_file_size.first.c_str(), oat_dex_file_size.second,
170002e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                           PercentOfOatBytes(oat_dex_file_size.second));
170105f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers      }
170205f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers
17032bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "\n" << StringPrintf("gc_map_bytes           = %7zd (%2.0f%% of oat file bytes)\n"
17042bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                 "pc_mapping_table_bytes = %7zd (%2.0f%% of oat file bytes)\n"
17052bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                 "vmap_table_bytes       = %7zd (%2.0f%% of oat file bytes)\n\n",
170605f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers                                 gc_map_bytes, PercentOfOatBytes(gc_map_bytes),
170705f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers                                 pc_mapping_table_bytes, PercentOfOatBytes(pc_mapping_table_bytes),
170805f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers                                 vmap_table_bytes, PercentOfOatBytes(vmap_table_bytes))
1709c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << std::flush;
1710916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
17112bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("dex_instruction_bytes = %zd\n", dex_instruction_bytes)
17122bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers         << StringPrintf("managed_code_bytes expansion = %.2f (ignoring deduplication %.2f)\n\n",
17132ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         static_cast<double>(managed_code_bytes) /
17142ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                             static_cast<double>(dex_instruction_bytes),
1715c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                         static_cast<double>(managed_code_bytes_ignoring_deduplication) /
1716cf44e6f1ec194a906f4760a7c0395fdb0123d7aeElliott Hughes                             static_cast<double>(dex_instruction_bytes))
1717c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << std::flush;
17183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
17193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOutliers(os);
1720916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1721916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  } stats_;
1722916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1723916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom private:
17240d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers  enum {
17250d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // Number of bytes for a constructor to be considered large. Based on the 1000 basic block
17260d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // threshold, we assume 2 bytes per instruction and 2 instructions per block.
17270d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    kLargeConstructorDexBytes = 4000,
17280d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // Number of bytes for a method to be considered large. Based on the 4000 basic block
17290d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // threshold, we assume 2 bytes per instruction and 2 instructions per block.
17300d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    kLargeMethodDexBytes = 16000
17310d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers  };
1732700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<OatDumper> oat_dumper_;
17332bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers  std::ostream* os_;
17341d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  gc::space::ImageSpace& image_space_;
17353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const ImageHeader& image_header_;
1736404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_mapping_table_;
1737404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_gc_map_;
1738d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
17393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  DISALLOW_COPY_AND_ASSIGN(ImageDumper);
174078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
174178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
174272395bf298b7707ad9d93c3e51b57e1b8e010311Elliott Hughesstatic int oatdump(int argc, char** argv) {
17430d39c12238499ca9ccc34d1532c443335e7c1044Elliott Hughes  InitLogging(argv);
174472395bf298b7707ad9d93c3e51b57e1b8e010311Elliott Hughes
174578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  // Skip over argv[0].
174678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argv++;
174778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argc--;
174878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
174978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (argc == 0) {
1750aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "No arguments specified\n");
175178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    usage();
175278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
175378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1754aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  const char* oat_filename = NULL;
17550f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  const char* image_location = NULL;
17560f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  const char* boot_image_location = NULL;
17570f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  InstructionSet instruction_set = kRuntimeISA;
17580cc6ab6c5104f565a0a3256b5b2b31c6383be189Logan Chien  std::string elf_filename_prefix;
175927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream* os = &std::cout;
1760700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<std::ofstream> out;
176154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  std::string output_name;
1762404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_mapping_table = false;
1763404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_gc_map = false;
176454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  bool symbolize = false;
176578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
176678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  for (int i = 0; i < argc; i++) {
176778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    const StringPiece option(argv[i]);
1768a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    if (option.starts_with("--oat-file=")) {
1769a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      oat_filename = option.substr(strlen("--oat-file=")).data();
1770aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    } else if (option.starts_with("--image=")) {
17710f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      image_location = option.substr(strlen("--image=")).data();
1772e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    } else if (option.starts_with("--boot-image=")) {
17730f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      boot_image_location = option.substr(strlen("--boot-image=")).data();
17740f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom    } else if (option.starts_with("--instruction-set=")) {
17750f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      StringPiece instruction_set_str = option.substr(strlen("--instruction-set=")).data();
17760f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      if (instruction_set_str == "arm") {
17770f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kThumb2;
17780f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      } else if (instruction_set_str == "arm64") {
17790f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kArm64;
17800f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      } else if (instruction_set_str == "mips") {
17810f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kMips;
17820f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      } else if (instruction_set_str == "x86") {
17830f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kX86;
17840f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      } else if (instruction_set_str == "x86_64") {
17850f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kX86_64;
17860f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      }
1787404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison    } else if (option.starts_with("--dump:")) {
1788404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        if (option == "--dump:raw_mapping_table") {
1789404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          dump_raw_mapping_table = true;
1790404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        } else if (option == "--dump:raw_gc_map") {
1791404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          dump_raw_gc_map = true;
1792404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        } else {
1793404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          fprintf(stderr, "Unknown argument %s\n", option.data());
1794404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          usage();
1795404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        }
179627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    } else if (option.starts_with("--output=")) {
179754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      output_name = option.substr(strlen("--output=")).ToString();
179854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      const char* filename = output_name.c_str();
179927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      out.reset(new std::ofstream(filename));
180027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      if (!out->good()) {
1801aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom        fprintf(stderr, "Failed to open output filename %s\n", filename);
180227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        usage();
180327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      }
180427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      os = out.get();
180554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    } else if (option.starts_with("--symbolize=")) {
180654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      oat_filename = option.substr(strlen("--symbolize=")).data();
180754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      symbolize = true;
180878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
1809aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Unknown argument %s\n", option.data());
181078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      usage();
181178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
181278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
181378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
18140f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  if (image_location == NULL && oat_filename == NULL) {
1815362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified\n");
1816362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
181778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
181878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
18190f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  if (image_location != NULL && oat_filename != NULL) {
1820362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified but not both\n");
1821362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
1822aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
1823aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
1824aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (oat_filename != NULL) {
18258d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    std::string error_msg;
18260c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien    OatFile* oat_file =
18278d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers        OatFile::Open(oat_filename, oat_filename, NULL, false, &error_msg);
1828aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (oat_file == NULL) {
18298d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      fprintf(stderr, "Failed to open oat file from '%s': %s\n", oat_filename, error_msg.c_str());
1830aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return EXIT_FAILURE;
1831aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
183254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (symbolize) {
183354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      OatSymbolizer oat_symbolizer(oat_file, output_name);
183454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      if (!oat_symbolizer.Init()) {
183554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        fprintf(stderr, "Failed to initialize symbolizer\n");
183654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        return EXIT_FAILURE;
183754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      }
183854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      if (!oat_symbolizer.Symbolize()) {
183954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        fprintf(stderr, "Failed to symbolize\n");
184054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        return EXIT_FAILURE;
184154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      }
184254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    } else {
184354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      OatDumper oat_dumper(*oat_file, dump_raw_mapping_table, dump_raw_gc_map);
184454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      oat_dumper.Dump(*os);
184554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
1846aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return EXIT_SUCCESS;
1847aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
1848aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
1849e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers  RuntimeOptions options;
185078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string image_option;
1851e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string oat_option;
185278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string boot_image_option;
1853e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string boot_oat_option;
18546c87180aef7d3127c0f25fcbc76e71f4a4f2b9faBrian Carlstrom
18556c87180aef7d3127c0f25fcbc76e71f4a4f2b9faBrian Carlstrom  // We are more like a compiler than a run-time. We don't want to execute code.
1856c0a1b18ac71ec0ff3ec0cca3cc8db9eb74e50690Brian Carlstrom  NoopCompilerCallbacks callbacks;
1857c0a1b18ac71ec0ff3ec0cca3cc8db9eb74e50690Brian Carlstrom  options.push_back(std::make_pair("compilercallbacks", &callbacks));
18586c87180aef7d3127c0f25fcbc76e71f4a4f2b9faBrian Carlstrom
18590f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  if (boot_image_location != NULL) {
186058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += "-Ximage:";
18610f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom    boot_image_option += boot_image_location;
186258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
186358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
18640f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  if (image_location != NULL) {
1865aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += "-Ximage:";
18660f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom    image_option += image_location;
1867aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
1868aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
18690f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  options.push_back(
18700f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      std::make_pair("imageinstructionset",
18710f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom                     reinterpret_cast<const void*>(GetInstructionSetString(instruction_set))));
187258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
187300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (!Runtime::Create(options, false)) {
1874aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Failed to create runtime\n");
187578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
187678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
1877700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<Runtime> runtime(Runtime::Current());
187800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
1879b9beb2e2efb6a204a69ca660d478b45f851e8f09Ian Rogers  // give it away now and then switch to a more manageable ScopedObjectAccess.
188000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
188100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
18821d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  gc::Heap* heap = Runtime::Current()->GetHeap();
18831d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  gc::space::ImageSpace* image_space = heap->GetImageSpace();
188478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  CHECK(image_space != NULL);
188578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const ImageHeader& image_header = image_space->GetImageHeader();
188678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (!image_header.IsValid()) {
18870f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom    fprintf(stderr, "Invalid image header %s\n", image_location);
188878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
188978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
18902ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom  ImageDumper image_dumper(os, *image_space, image_header,
18912ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           dump_raw_mapping_table, dump_raw_gc_map);
18923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  image_dumper.Dump();
189378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return EXIT_SUCCESS;
189478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
189578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
18967934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
189778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
189878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint main(int argc, char** argv) {
189978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return art::oatdump(argc, argv);
190078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
1901