oatdump.cc revision 2ed8deff799448e094fa7a7cb9cf3b718820f4c6
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(),
2235182932cf6704b53e957f7b4be021fe505a55e22Andreas Gampe                    it.GetMethodCodeItem(), it.GetMethodAccessFlags(), 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(),
2305182932cf6704b53e957f7b4be021fe505a55e22Andreas Gampe                    it.GetMethodCodeItem(), it.GetMethodAccessFlags(), 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
3893946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray    os << "IMAGE PATCH DELTA:\n" << oat_header.GetImagePatchDelta() << "\n\n";
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];
4202ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      CHECK(oat_dex_file != nullptr);
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());
4542ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe        if (class_def != nullptr) {
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    }
4622ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    return nullptr;
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];
4732ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      CHECK(oat_dex_file != nullptr);
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);
4882ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe        if (class_data != nullptr) {
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));
5302ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (dex_file.get() == nullptr) {
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);
5642ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (class_data == nullptr) {  // 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,
5735182932cf6704b53e957f7b4be021fe505a55e22Andreas Gampe                    it.GetMemberIndex(), it.GetMethodCodeItem(), it.GetRawMemberAccessFlags());
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,
5805182932cf6704b53e957f7b4be021fe505a55e22Andreas Gampe                    it.GetMemberIndex(), it.GetMethodCodeItem(), it.GetRawMemberAccessFlags());
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    }
6042ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe
6052ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    std::unique_ptr<verifier::MethodVerifier> verifier;
6062ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (Runtime::Current() != nullptr) {
607a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent1_os << "VERIFIER TYPE ANALYSIS:\n";
6082ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      verifier.reset(DumpVerifier(*indent2_os, dex_method_idx, &dex_file, class_def, code_item,
6092ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                  method_access_flags));
6102bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
6112bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    {
612a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent1_os << "OAT DATA:\n";
613a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe
614a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("frame_size_in_bytes: %zd\n", oat_method.GetFrameSizeInBytes());
615a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("core_spill_mask: 0x%08x ", oat_method.GetCoreSpillMask());
616a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      DumpSpillMask(*indent2_os, oat_method.GetCoreSpillMask(), false);
617a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("\nfp_spill_mask: 0x%08x ", oat_method.GetFpSpillMask());
618a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      DumpSpillMask(*indent2_os, oat_method.GetFpSpillMask(), true);
619a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("\nvmap_table: %p (offset=0x%08x)\n",
620a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe                                  oat_method.GetVmapTable(), oat_method.GetVmapTableOffset());
6213946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray
6223946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      if (oat_method.GetNativeGcMap() != nullptr) {
6233946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        // The native GC map is null for methods compiled with the optimizing compiler.
6243946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray        DumpVmap(*indent2_os, oat_method);
6253946844c34ad965515f677084b07d663d70ad1b8Nicolas Geoffray      }
626faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      DumpVregLocations(*indent2_os, oat_method, code_item);
627a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("mapping_table: %p (offset=0x%08x)\n",
628a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe                                  oat_method.GetMappingTable(), oat_method.GetMappingTableOffset());
629404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison      if (dump_raw_mapping_table_) {
630a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe        Indenter indent3_filter(indent2_os->rdbuf(), kIndentChar, kIndentBy1Count);
6312bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        std::ostream indent3_os(&indent3_filter);
6322bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        DumpMappingTable(indent3_os, oat_method);
6332bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
634a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent2_os << StringPrintf("gc_map: %p (offset=0x%08x)\n",
635a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe                                  oat_method.GetNativeGcMap(), oat_method.GetNativeGcMapOffset());
636404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison      if (dump_raw_gc_map_) {
637a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe        Indenter indent3_filter(indent2_os->rdbuf(), kIndentChar, kIndentBy1Count);
6382bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        std::ostream indent3_os(&indent3_filter);
6392bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        DumpGcMap(indent3_os, oat_method, code_item);
6402bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
6412bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
6422bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    {
643ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const void* code = oat_method.GetQuickCode();
644ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      uint32_t code_size = oat_method.GetQuickCodeSize();
645ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if (code == nullptr) {
646ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        code = oat_method.GetPortableCode();
647ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        code_size = oat_method.GetPortableCodeSize();
648ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      }
649a8b41aaa08283390606e6515d178ca3cc4c6ca41Andreas Gampe      *indent1_os << StringPrintf("CODE: %p (offset=0x%08x size=%d)%s\n",
650ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                                 code,
6512bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                 oat_method.GetCodeOffset(),
652ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                                 code_size,
653ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                                 code != nullptr ? "..." : "");
654590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier
6552ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      DumpCode(*indent2_os, verifier.get(), oat_method, code_item);
6562bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
6573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
6583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
6593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpSpillMask(std::ostream& os, uint32_t spill_mask, bool is_float) {
6603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (spill_mask == 0) {
6613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
6623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
6632bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "(";
6643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < 32; i++) {
6653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if ((spill_mask & (1 << i)) != 0) {
6663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (is_float) {
6673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << "fr" << i;
6683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        } else {
6693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << "r" << i;
6703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
6713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        spill_mask ^= 1 << i;  // clear bit
6723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (spill_mask != 0) {
6733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << ", ";
6743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        } else {
6753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          break;
6763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
6773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
6783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
6793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << ")";
6803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
6813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
682b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpVmap(std::ostream& os, const OatFile::OatMethod& oat_method) {
6831809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    const uint8_t* raw_table = oat_method.GetVmapTable();
6842ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (raw_table != nullptr) {
6851809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      const VmapTable vmap_table(raw_table);
6861809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      bool first = true;
6871809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      bool processing_fp = false;
6881809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      uint32_t spill_mask = oat_method.GetCoreSpillMask();
6891809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      for (size_t i = 0; i < vmap_table.Size(); i++) {
6901809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        uint16_t dex_reg = vmap_table[i];
6911809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        uint32_t cpu_reg = vmap_table.ComputeRegister(spill_mask, i,
6921809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers                                                      processing_fp ? kFloatVReg : kIntVReg);
6931809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << (first ? "v" : ", v")  << dex_reg;
6941809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        if (!processing_fp) {
6951809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          os << "/r" << cpu_reg;
6961809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        } else {
6971809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          os << "/fr" << cpu_reg;
6981809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
6991809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        first = false;
7001809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        if (!processing_fp && dex_reg == 0xFFFF) {
7011809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          processing_fp = true;
7021809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          spill_mask = oat_method.GetFpSpillMask();
7031809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
7043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
7051809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      os << "\n";
7063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
7073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
7083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
709faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru  void DumpVregLocations(std::ostream& os, const OatFile::OatMethod& oat_method,
710faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru                         const DexFile::CodeItem* code_item) {
711faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru    if (code_item != nullptr) {
712faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      size_t num_locals_ins = code_item->registers_size_;
713faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      size_t num_ins = code_item->ins_size_;
714faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      size_t num_locals = num_locals_ins - num_ins;
715faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      size_t num_outs = code_item->outs_size_;
716faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
717faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      os << "vr_stack_locations:";
718faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      for (size_t reg = 0; reg <= num_locals_ins; reg++) {
719faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        // For readability, delimit the different kinds of VRs.
720faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        if (reg == num_locals_ins) {
721faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru          os << "\n\tmethod*:";
722faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        } else if (reg == num_locals && num_ins > 0) {
723faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru          os << "\n\tins:";
724faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        } else if (reg == 0 && num_locals > 0) {
725faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru          os << "\n\tlocals:";
726faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        }
727faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
728faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        uint32_t offset = StackVisitor::GetVRegOffset(code_item, oat_method.GetCoreSpillMask(),
729faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru                                                      oat_method.GetFpSpillMask(),
730faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru                                                      oat_method.GetFrameSizeInBytes(), reg,
731faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru                                                      GetInstructionSet());
732faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        os << " v" << reg << "[sp + #" << offset << "]";
733faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      }
734faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
735faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      for (size_t out_reg = 0; out_reg < num_outs; out_reg++) {
736faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        if (out_reg == 0) {
737faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru          os << "\n\touts:";
738faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        }
739faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
740faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        uint32_t offset = StackVisitor::GetOutVROffset(out_reg, GetInstructionSet());
741faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru        os << " v" << out_reg << "[sp + #" << offset << "]";
742faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      }
743faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
744faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru      os << "\n";
745faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru    }
746faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru  }
747faf9f0d53573025dc5ae5ff6c4412396030cf1daRazvan A Lupusoru
748b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DescribeVReg(std::ostream& os, const OatFile::OatMethod& oat_method,
7492bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                    const DexFile::CodeItem* code_item, size_t reg, VRegKind kind) {
7501809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    const uint8_t* raw_table = oat_method.GetVmapTable();
7512ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (raw_table != nullptr) {
752b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      const VmapTable vmap_table(raw_table);
753b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      uint32_t vmap_offset;
7541809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      if (vmap_table.IsInContext(reg, kind, &vmap_offset)) {
7552bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        bool is_float = (kind == kFloatVReg) || (kind == kDoubleLoVReg) || (kind == kDoubleHiVReg);
7562bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        uint32_t spill_mask = is_float ? oat_method.GetFpSpillMask()
7572bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                       : oat_method.GetCoreSpillMask();
7582bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << (is_float ? "fr" : "r") << vmap_table.ComputeRegister(spill_mask, vmap_offset, kind);
759b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      } else {
760b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        uint32_t offset = StackVisitor::GetVRegOffset(code_item, oat_method.GetCoreSpillMask(),
761b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                                                      oat_method.GetFpSpillMask(),
76242fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray                                                      oat_method.GetFrameSizeInBytes(), reg,
76342fcd9838a87abaf7a2ef86853a5287f86dbe391Nicolas Geoffray                                                      GetInstructionSet());
764b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        os << "[sp + #" << offset << "]";
765b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
766b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    }
767b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
768b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers
769ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  void DumpGcMapRegisters(std::ostream& os, const OatFile::OatMethod& oat_method,
770ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                          const DexFile::CodeItem* code_item,
771ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers                          size_t num_regs, const uint8_t* reg_bitmap) {
772ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    bool first = true;
773ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    for (size_t reg = 0; reg < num_regs; reg++) {
774ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) {
775ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        if (first) {
776ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          os << "  v" << reg << " (";
777ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
778ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          os << ")";
779ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          first = false;
780ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        } else {
781ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          os << ", v" << reg << " (";
782ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
783ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          os << ")";
784ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        }
785ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      }
786ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
787ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (first) {
788ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      os << "No registers in GC map\n";
789ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else {
790ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      os << "\n";
791ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    }
792ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  }
793b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpGcMap(std::ostream& os, const OatFile::OatMethod& oat_method,
794b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers                 const DexFile::CodeItem* code_item) {
795b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint8_t* gc_map_raw = oat_method.GetNativeGcMap();
796ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (gc_map_raw == nullptr) {
797ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      return;  // No GC map.
7983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
799ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* quick_code = oat_method.GetQuickCode();
800ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (quick_code != nullptr) {
801ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      NativePcOffsetToReferenceMap map(gc_map_raw);
802ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      for (size_t entry = 0; entry < map.NumEntries(); entry++) {
803ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(quick_code) +
804ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            map.GetNativePcOffset(entry);
805ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        os << StringPrintf("%p", native_pc);
806ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DumpGcMapRegisters(os, oat_method, code_item, map.RegWidth() * 8, map.GetBitMap(entry));
807ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      }
808ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else {
809ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const void* portable_code = oat_method.GetPortableCode();
810ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      CHECK(portable_code != nullptr);
811ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      verifier::DexPcToReferenceMap map(gc_map_raw);
812ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      for (size_t entry = 0; entry < map.NumEntries(); entry++) {
813ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        uint32_t dex_pc = map.GetDexPc(entry);
814ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        os << StringPrintf("0x%08x", dex_pc);
815ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DumpGcMapRegisters(os, oat_method, code_item, map.RegWidth() * 8, map.GetBitMap(entry));
8163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
8173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
818aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
819e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
8203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpMappingTable(std::ostream& os, const OatFile::OatMethod& oat_method) {
821ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* quick_code = oat_method.GetQuickCode();
822ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (quick_code == nullptr) {
8232bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      return;
8242bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
8251809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    MappingTable table(oat_method.GetMappingTable());
8261809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    if (table.TotalSize() != 0) {
8271809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
8281809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      std::ostream indent_os(&indent_filter);
8291809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      if (table.PcToDexSize() != 0) {
8301809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        typedef MappingTable::PcToDexIterator It;
8311809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << "suspend point mappings {\n";
8321809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
8331809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          indent_os << StringPrintf("0x%04x -> 0x%04x\n", cur.NativePcOffset(), cur.DexPc());
8341809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
8351809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << "}\n";
8361809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      }
8371809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      if (table.DexToPcSize() != 0) {
8381809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        typedef MappingTable::DexToPcIterator It;
8391809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << "catch entry mappings {\n";
8401809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        for (It cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
8411809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          indent_os << StringPrintf("0x%04x -> 0x%04x\n", cur.NativePcOffset(), cur.DexPc());
8421809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
8431809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        os << "}\n";
8443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
8453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
8463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
8473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
8481809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers  uint32_t DumpMappingAtOffset(std::ostream& os, const OatFile::OatMethod& oat_method,
8491809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers                               size_t offset, bool suspend_point_mapping) {
8501809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    MappingTable table(oat_method.GetMappingTable());
8511809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    if (suspend_point_mapping && table.PcToDexSize() > 0) {
8521809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      typedef MappingTable::PcToDexIterator It;
8531809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
8541809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        if (offset == cur.NativePcOffset()) {
8554b8c13ee44c4c959d7b8de9adff7ce6df48c31d0Brian Carlstrom          os << StringPrintf("suspend point dex PC: 0x%04x\n", cur.DexPc());
8561809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          return cur.DexPc();
8571809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        }
858b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
8591809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers    } else if (!suspend_point_mapping && table.DexToPcSize() > 0) {
8601809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      typedef MappingTable::DexToPcIterator It;
8611809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers      for (It cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
8621809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers        if (offset == cur.NativePcOffset()) {
8634b8c13ee44c4c959d7b8de9adff7ce6df48c31d0Brian Carlstrom          os << StringPrintf("catch entry dex PC: 0x%04x\n", cur.DexPc());
8641809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers          return cur.DexPc();
865b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
866b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
8673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
8682bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    return DexFile::kDexNoIndex;
869b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
8703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
8712bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers  void DumpGcMapAtNativePcOffset(std::ostream& os, const OatFile::OatMethod& oat_method,
8722bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                 const DexFile::CodeItem* code_item, size_t native_pc_offset) {
873b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    const uint8_t* gc_map_raw = oat_method.GetNativeGcMap();
8742ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (gc_map_raw != nullptr) {
875b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      NativePcOffsetToReferenceMap map(gc_map_raw);
8762bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      if (map.HasEntry(native_pc_offset)) {
877b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        size_t num_regs = map.RegWidth() * 8;
8782bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        const uint8_t* reg_bitmap = map.FindBitMap(native_pc_offset);
879b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        bool first = true;
880b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        for (size_t reg = 0; reg < num_regs; reg++) {
881b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) {
882b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            if (first) {
8832bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              os << "GC map objects:  v" << reg << " (";
8842bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
885b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << ")";
886b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              first = false;
887b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            } else {
888b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << ", v" << reg << " (";
8892bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              DescribeVReg(os, oat_method, code_item, reg, kReferenceVReg);
890b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers              os << ")";
891b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers            }
892b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          }
893b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
894b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        if (!first) {
895b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers          os << "\n";
896b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        }
897b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      }
8983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
899b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
9003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
901590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  void DumpVRegsAtDexPc(std::ostream& os, verifier::MethodVerifier* verifier,
902590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier                        const OatFile::OatMethod& oat_method,
903590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier                        const DexFile::CodeItem* code_item, uint32_t dex_pc) {
904590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier    DCHECK(verifier != nullptr);
9057b3ddd27c223fcce784314f78fda7f67dcb37730Ian Rogers    std::vector<int32_t> kinds = verifier->DescribeVRegs(dex_pc);
9062bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    bool first = true;
9072bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    for (size_t reg = 0; reg < code_item->registers_size_; reg++) {
9082bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      VRegKind kind = static_cast<VRegKind>(kinds.at(reg * 2));
9092bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      if (kind != kUndefined) {
9102bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        if (first) {
9112bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          os << "VRegs:  v";
9122bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          first = false;
9132bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        } else {
9142bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          os << ", v";
9152bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        }
9162bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << reg << " (";
9172bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        switch (kind) {
9182bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          case kImpreciseConstant:
9192bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            os << "Imprecise Constant: " << kinds.at((reg * 2) + 1) << ", ";
9202bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            DescribeVReg(os, oat_method, code_item, reg, kind);
9212bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            break;
9222bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          case kConstant:
9232bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            os << "Constant: " << kinds.at((reg * 2) + 1);
9242bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            break;
9252bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          default:
9262bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            DescribeVReg(os, oat_method, code_item, reg, kind);
9272bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            break;
9282bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        }
9292bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << ")";
9302bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
9312bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
9322bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    if (!first) {
9332bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "\n";
9342bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
9352bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers  }
9362bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
9372bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
938b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  void DumpDexCode(std::ostream& os, const DexFile& dex_file, const DexFile::CodeItem* code_item) {
9392ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (code_item != nullptr) {
940b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      size_t i = 0;
941b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      while (i < code_item->insns_size_in_code_units_) {
942b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        const Instruction* instruction = Instruction::At(&code_item->insns_[i]);
9432bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("0x%04zx: %s\n", i, instruction->DumpString(&dex_file).c_str());
944b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers        i += instruction->SizeInCodeUnits();
945e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
946e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
947b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
948b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers
9492ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  verifier::MethodVerifier* DumpVerifier(std::ostream& os, uint32_t dex_method_idx,
9502ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                         const DexFile* dex_file,
9512ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                         const DexFile::ClassDef& class_def,
9522ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                         const DexFile::CodeItem* code_item,
9532ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                         uint32_t method_access_flags) {
9542bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    if ((method_access_flags & kAccNative) == 0) {
9552bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      ScopedObjectAccess soa(Thread::Current());
956bf99f77dda749e2b653e8c45259b1fb56e7bb012Mathieu Chartier      StackHandleScope<1> hs(soa.Self());
957eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier      Handle<mirror::DexCache> dex_cache(
958eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier          hs.NewHandle(Runtime::Current()->GetClassLinker()->FindDexCache(*dex_file)));
9592ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      return verifier::MethodVerifier::VerifyMethodAndDump(soa.Self(), os, dex_method_idx, dex_file,
9602ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                                           dex_cache,
9612ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                                           NullHandle<mirror::ClassLoader>(),
9622ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                                           &class_def, code_item,
9632ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                                           NullHandle<mirror::ArtMethod>(),
9642ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe                                                           method_access_flags);
9652bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    }
9662ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe
9672ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    return nullptr;
9682bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers  }
9692bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
970590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier  void DumpCode(std::ostream& os, verifier::MethodVerifier* verifier,
971590fee9e8972f872301c2d16a575d579ee564beeMathieu Chartier                const OatFile::OatMethod& oat_method, const DexFile::CodeItem* code_item) {
972ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* portable_code = oat_method.GetPortableCode();
973ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* quick_code = oat_method.GetQuickCode();
974ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers
975ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    size_t code_size = oat_method.GetQuickCodeSize();
976ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if ((code_size == 0) || ((portable_code == nullptr) && (quick_code == nullptr))) {
9772bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "NO CODE!\n";
978b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers      return;
979ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else if (quick_code != nullptr) {
980ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      const uint8_t* quick_native_pc = reinterpret_cast<const uint8_t*>(quick_code);
981ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      size_t offset = 0;
982ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      while (offset < code_size) {
983ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DumpMappingAtOffset(os, oat_method, offset, false);
984ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        offset += disassembler_->Dump(os, quick_native_pc + offset);
985ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        uint32_t dex_pc = DumpMappingAtOffset(os, oat_method, offset, true);
986ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        if (dex_pc != DexFile::kDexNoIndex) {
987ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          DumpGcMapAtNativePcOffset(os, oat_method, code_item, offset);
988ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          if (verifier != nullptr) {
989ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            DumpVRegsAtDexPc(os, verifier, oat_method, code_item, dex_pc);
990ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          }
9912bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        }
9922bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
993ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    } else {
994ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      CHECK(portable_code != nullptr);
995ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      CHECK_EQ(code_size, 0U);  // TODO: disassembly of portable is currently not supported.
996b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers    }
997b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers  }
998b23a7729cf7855fa05345d03a4d84111d5ec7172Ian Rogers
9993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const OatFile& oat_file_;
10003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  std::vector<const OatFile::OatDexFile*> oat_dex_files_;
1001404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_mapping_table_;
1002404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_gc_map_;
1003ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  std::set<uintptr_t> offsets_;
1004700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<Disassembler> disassembler_;
1005aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom};
1006aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
10073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogersclass ImageDumper {
100827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom public:
10092ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom  explicit ImageDumper(std::ostream* os, gc::space::ImageSpace& image_space,
1010404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison                       const ImageHeader& image_header, bool dump_raw_mapping_table,
1011404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison                       bool dump_raw_gc_map)
10122ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom      : os_(os), image_space_(image_space), image_header_(image_header),
1013404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        dump_raw_mapping_table_(dump_raw_mapping_table),
1014404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        dump_raw_gc_map_(dump_raw_gc_map) {}
101527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
1016b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers  void Dump() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
10172bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    std::ostream& os = *os_;
10182bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "MAGIC: " << image_header_.GetMagic() << "\n\n";
10192bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
10202bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "IMAGE BEGIN: " << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n";
10212bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
102231e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier    os << "IMAGE BITMAP OFFSET: " << reinterpret_cast<void*>(image_header_.GetImageBitmapOffset())
102331e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier       << " SIZE: " << reinterpret_cast<void*>(image_header_.GetImageBitmapSize()) << "\n\n";
102431e8925781c2302f1d1a9b39e216ba415bfe0d7eMathieu Chartier
10252bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "OAT CHECKSUM: " << StringPrintf("0x%08x\n\n", image_header_.GetOatChecksum());
10262bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
1027700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    os << "OAT FILE BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatFileBegin()) << "\n\n";
10282bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
1029700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    os << "OAT DATA BEGIN:" << reinterpret_cast<void*>(image_header_.GetOatDataBegin()) << "\n\n";
1030700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
1031700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    os << "OAT DATA END:" << reinterpret_cast<void*>(image_header_.GetOatDataEnd()) << "\n\n";
1032700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom
1033700c8d31733534a3d978b75a03f6f7e177dc7e81Brian Carlstrom    os << "OAT FILE END:" << reinterpret_cast<void*>(image_header_.GetOatFileEnd()) << "\n\n";
10342bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers
1035a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    os << "PATCH DELTA:" << image_header_.GetPatchDelta() << "\n\n";
1036a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light
10372bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    {
10382bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "ROOTS: " << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n";
10392bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      Indenter indent1_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
10402bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      std::ostream indent1_os(&indent1_filter);
10412bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax));
10422bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
10432bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
10442bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        const char* image_root_description = image_roots_descriptions_[i];
10452dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers        mirror::Object* image_root_object = image_header_.GetImageRoot(image_root);
10462bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        indent1_os << StringPrintf("%s: %p\n", image_root_description, image_root_object);
10472bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        if (image_root_object->IsObjectArray()) {
10482bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          Indenter indent2_filter(indent1_os.rdbuf(), kIndentChar, kIndentBy1Count);
10492bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          std::ostream indent2_os(&indent2_filter);
10502dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers          mirror::ObjectArray<mirror::Object>* image_root_object_array
1051fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              = image_root_object->AsObjectArray<mirror::Object>();
10522bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          for (int i = 0; i < image_root_object_array->GetLength(); i++) {
10532dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers            mirror::Object* value = image_root_object_array->Get(i);
1054fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            size_t run = 0;
1055fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            for (int32_t j = i + 1; j < image_root_object_array->GetLength(); j++) {
1056fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              if (value == image_root_object_array->Get(j)) {
1057fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers                run++;
1058fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              } else {
1059fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers                break;
1060fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              }
1061fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            }
1062fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            if (run == 0) {
1063fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              indent2_os << StringPrintf("%d: ", i);
1064fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            } else {
1065fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              indent2_os << StringPrintf("%d to %zd: ", i, i + run);
1066fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers              i = i + run;
1067fa82427c68b09f4aedbee319dc71579afbfc66f5Ian Rogers            }
10682ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe            if (value != nullptr) {
10692bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              PrettyObjectValue(indent2_os, value->GetClass(), value);
10702bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            } else {
10712bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers              indent2_os << i << ": null\n";
10722bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            }
1073d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
107434f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        }
107534f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      }
107627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    }
10772bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "\n";
107827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
1079aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
10802ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    std::string image_filename = image_space_.GetImageFilename();
10812ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom    std::string oat_location = ImageHeader::GetOatLocationFromImageLocation(image_filename);
10822bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "OAT LOCATION: " << oat_location;
10832bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "\n";
10848d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    std::string error_msg;
1085a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    const OatFile* oat_file = class_linker->FindOpenedOatFileFromOatLocation(oat_location);
1086a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light    if (oat_file == nullptr) {
10872ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      oat_file = OatFile::Open(oat_location, oat_location, nullptr, false, &error_msg);
1088a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light      if (oat_file == nullptr) {
1089a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light        os << "NOT FOUND: " << error_msg << "\n";
1090a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light        return;
1091a59dd80f9f48cb750d329d4d4af2d99d72b484d1Alex Light      }
1092aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
10932bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "\n";
1094aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
10953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.oat_file_bytes = oat_file->Size();
109678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
10979583fbcf597eff6d0b3c5359b8e8d5f70ed82c40Nicolas Geoffray    oat_dumper_.reset(new OatDumper(*oat_file, dump_raw_mapping_table_,
1098404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        dump_raw_gc_map_));
10993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
110002e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier    for (const OatFile::OatDexFile* oat_dex_file : oat_file->GetOatDexFiles()) {
11012ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      CHECK(oat_dex_file != nullptr);
110202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      stats_.oat_dex_file_sizes.push_back(std::make_pair(oat_dex_file->GetDexFileLocation(),
110302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                                                         oat_dex_file->FileSize()));
110405f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers    }
110505f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers
11062bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "OBJECTS:\n" << std::flush;
1107b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier
1108b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    // Loop through all the image spaces and dump their objects.
11091d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    gc::Heap* heap = Runtime::Current()->GetHeap();
11101d54e73444e017d3a65234e0f193846f3e27472bIan Rogers    const std::vector<gc::space::ContinuousSpace*>& spaces = heap->GetContinuousSpaces();
111150b35e2fd1a68cd1240e4a9d9f363e11764957d1Ian Rogers    Thread* self = Thread::Current();
1112357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    {
1113c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier      {
1114c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
1115c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        heap->FlushAllocStack();
1116c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier      }
111790d706849a09590f150748ff97256ef718aca441Hiroshi Yamauchi      // Since FlushAllocStack() above resets the (active) allocation
111890d706849a09590f150748ff97256ef718aca441Hiroshi Yamauchi      // stack. Need to revoke the thread-local allocation stacks that
111990d706849a09590f150748ff97256ef718aca441Hiroshi Yamauchi      // point into it.
1120c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier      {
1121c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        self->TransitionFromRunnableToSuspended(kNative);
1122c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        ThreadList* thread_list = Runtime::Current()->GetThreadList();
1123c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        thread_list->SuspendAll();
1124c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        heap->RevokeAllThreadLocalAllocationStacks(self);
1125c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        thread_list->ResumeAll();
1126c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier        self->TransitionFromSuspendedToRunnable();
1127c22c59ef8513b4cbbfd25073d1afbf58196b522aMathieu Chartier      }
1128357e9be24c17a6bc2ae9fb53f25c73503116101dMathieu Chartier    }
11292bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    {
11302bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      std::ostream* saved_os = os_;
11312bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
11322bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      std::ostream indent_os(&indent_filter);
11332bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os_ = &indent_os;
11342bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
113502e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      for (const auto& space : spaces) {
11362bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        if (space->IsImageSpace()) {
11371d54e73444e017d3a65234e0f193846f3e27472bIan Rogers          gc::space::ImageSpace* image_space = space->AsImageSpace();
11382bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          image_space->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
11392bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          indent_os << "\n";
11402bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        }
11412fde53367dbe721e5273c34b590e67112322cc9eMathieu Chartier      }
11422bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      // Dump the large objects separately.
1143bbd695c71e0bf518f582e84524e1cdeb3de3896cMathieu Chartier      heap->GetLargeObjectsSpace()->GetLiveBitmap()->Walk(ImageDumper::Callback, this);
11442bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      indent_os << "\n";
11452bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os_ = saved_os;
1146b062fdd4cb097fbae69b4bcb479c34d83ecab8caMathieu Chartier    }
11472bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "STATS:\n" << std::flush;
1148700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers    std::unique_ptr<File> file(OS::OpenFileForReading(image_filename.c_str()));
11492ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (file.get() == nullptr) {
11502ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom      LOG(WARNING) << "Failed to find image in " << image_filename;
11516f277751ec5bfc0d7469b2cc7f7134e9032593f1Brian Carlstrom    }
11522ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (file.get() != nullptr) {
11532ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom      stats_.file_bytes = file->GetLength();
11546f277751ec5bfc0d7469b2cc7f7134e9032593f1Brian Carlstrom    }
11553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t header_bytes = sizeof(ImageHeader);
11563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.header_bytes = header_bytes;
11573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t alignment_bytes = RoundUp(header_bytes, kObjectAlignment) - header_bytes;
11583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.alignment_bytes += alignment_bytes;
115932327098e300ab66671b891a18bf669576fc896aMathieu Chartier    stats_.alignment_bytes += image_header_.GetImageBitmapOffset() - image_header_.GetImageSize();
116032327098e300ab66671b891a18bf669576fc896aMathieu Chartier    stats_.bitmap_bytes += image_header_.GetImageBitmapSize();
11612bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    stats_.Dump(os);
11622bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << "\n";
116327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
11642bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    os << std::flush;
11653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
11662bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    oat_dumper_->Dump(os);
11673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
1168d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
11693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers private:
11702dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static void PrettyObjectValue(std::ostream& os, mirror::Class* type, mirror::Object* value)
1171b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
11722ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    CHECK(type != nullptr);
11732ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (value == nullptr) {
11742bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("null   %s\n", PrettyDescriptor(type).c_str());
1175d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsStringClass()) {
11762dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::String* string = value->AsString();
11772bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   String: %s\n", string,
117868b56858367e29461ae290fd797443a1ef6d8005Ian Rogers                         PrintableString(string->ToModifiedUtf8().c_str()).c_str());
117964b6d145fa53b8dfb07a8fc2426af13f155d5a4dIan Rogers    } else if (type->IsClassClass()) {
11802dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Class* klass = value->AsClass();
11812bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   Class: %s\n", klass, PrettyDescriptor(klass).c_str());
1182ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (type->IsArtFieldClass()) {
1183ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtField* field = value->AsArtField();
11842bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   Field: %s\n", field, PrettyField(field).c_str());
1185ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (type->IsArtMethodClass()) {
1186ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtMethod* method = value->AsArtMethod();
11872bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   Method: %s\n", method, PrettyMethod(method).c_str());
1188d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
11892bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p   %s\n", value, PrettyDescriptor(type).c_str());
1190d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
1191d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
1192d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
1193ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom  static void PrintField(std::ostream& os, mirror::ArtField* field, mirror::Object* obj)
1194b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
119561c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    const char* descriptor = field->GetTypeDescriptor();
119661c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier    os << StringPrintf("%s: ", field->GetName());
119748efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers    if (descriptor[0] != 'L' && descriptor[0] != '[') {
119861c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier      StackHandleScope<1> hs(Thread::Current());
119961c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier      FieldHelper fh(hs.NewHandle(field));
12002dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Class* type = fh.GetType();
120137f05ef45e0393de812d51261dc293240c17294dFred Shih      DCHECK(type->IsPrimitive());
120248efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      if (type->IsPrimitiveLong()) {
1203ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        os << StringPrintf("%" PRId64 " (0x%" PRIx64 ")\n", field->Get64(obj), field->Get64(obj));
120448efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else if (type->IsPrimitiveDouble()) {
12052bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj));
120648efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else if (type->IsPrimitiveFloat()) {
12072bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%f (%a)\n", field->GetFloat(obj), field->GetFloat(obj));
120837f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveInt()) {
12092bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%d (0x%x)\n", field->Get32(obj), field->Get32(obj));
121037f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveChar()) {
121137f05ef45e0393de812d51261dc293240c17294dFred Shih        os << StringPrintf("%u (0x%x)\n", field->GetChar(obj), field->GetChar(obj));
121237f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveShort()) {
121337f05ef45e0393de812d51261dc293240c17294dFred Shih        os << StringPrintf("%d (0x%x)\n", field->GetShort(obj), field->GetShort(obj));
121437f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveBoolean()) {
121537f05ef45e0393de812d51261dc293240c17294dFred Shih        os << StringPrintf("%s (0x%x)\n", field->GetBoolean(obj)? "true" : "false",
121637f05ef45e0393de812d51261dc293240c17294dFred Shih            field->GetBoolean(obj));
121737f05ef45e0393de812d51261dc293240c17294dFred Shih      } else if (type->IsPrimitiveByte()) {
121837f05ef45e0393de812d51261dc293240c17294dFred Shih        os << StringPrintf("%d (0x%x)\n", field->GetByte(obj), field->GetByte(obj));
121937f05ef45e0393de812d51261dc293240c17294dFred Shih      } else {
122037f05ef45e0393de812d51261dc293240c17294dFred Shih        LOG(FATAL) << "Unknown type: " << PrettyClass(type);
122148efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      }
1222d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
122348efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      // Get the value, don't compute the type unless it is non-null as we don't want
122448efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      // to cause class loading.
12252dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Object* value = field->GetObj(obj);
12262ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      if (value == nullptr) {
12272bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("null   %s\n", PrettyDescriptor(descriptor).c_str());
122848efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      } else {
122950239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers        // Grab the field type without causing resolution.
123061c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier        StackHandleScope<1> hs(Thread::Current());
123161c5ebc6aee2cac1c363de6fbdac25ada1697fdbMathieu Chartier        FieldHelper fh(hs.NewHandle(field));
123250239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers        mirror::Class* field_type = fh.GetType(false);
12332ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe        if (field_type != nullptr) {
123450239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers          PrettyObjectValue(os, field_type, value);
123550239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers        } else {
123650239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers          os << StringPrintf("%p   %s\n", value, PrettyDescriptor(descriptor).c_str());
123750239c75041df9e12f9cbb018ccc08af6890e102Ian Rogers        }
123848efc2b5c4b95ac507de5150cd315c6e1c96b381Ian Rogers      }
1239d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
1240d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
1241d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
12422dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static void DumpFields(std::ostream& os, mirror::Object* obj, mirror::Class* klass)
1243b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
12442dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* super = klass->GetSuperClass();
12452ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (super != nullptr) {
12462bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      DumpFields(os, obj, super);
1247d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
1248ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    mirror::ObjectArray<mirror::ArtField>* fields = klass->GetIFields();
12492ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (fields != nullptr) {
1250d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < fields->GetLength(); i++) {
1251ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom        mirror::ArtField* field = fields->Get(i);
12522bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        PrintField(os, field, obj);
1253d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
1254d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
1255d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
1256d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
12572dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  bool InDumpSpace(const mirror::Object* object) {
12583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return image_space_.Contains(object);
1259f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
12603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1261ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  const void* GetQuickOatCodeBegin(mirror::ArtMethod* m)
1262b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1263ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const void* quick_code = m->GetEntryPointFromQuickCompiledCode();
126498d1cc8033251c93786e2fa8c59a2e555a9493beMingyao Yang    if (quick_code == Runtime::Current()->GetClassLinker()->GetQuickResolutionTrampoline()) {
1265ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      quick_code = oat_dumper_->GetQuickOatCode(m);
12663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
1267f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    if (oat_dumper_->GetInstructionSet() == kThumb2) {
1268ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers      quick_code = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(quick_code) & ~0x1);
1269f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
1270ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return quick_code;
12713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
12723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1273ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  uint32_t GetQuickOatCodeSize(mirror::ArtMethod* m)
1274b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1275ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetQuickOatCodeBegin(m));
1276ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    if (oat_code_begin == nullptr) {
1277f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom      return 0;
1278f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
1279f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    return oat_code_begin[-1];
1280f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
1281f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
1282ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers  const void* GetQuickOatCodeEnd(mirror::ArtMethod* m)
1283b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
1284ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetQuickOatCodeBegin(m));
12852ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (oat_code_begin == nullptr) {
12862ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      return nullptr;
1287f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
1288ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers    return oat_code_begin + GetQuickOatCodeSize(m);
1289f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
1290f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
12912dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers  static void Callback(mirror::Object* obj, void* arg)
1292b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
12932ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    DCHECK(obj != nullptr);
12942ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    DCHECK(arg != nullptr);
12953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    ImageDumper* state = reinterpret_cast<ImageDumper*>(arg);
129678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    if (!state->InDumpSpace(obj)) {
129778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      return;
129878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
1299916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1300916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes = obj->SizeOf();
1301916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
1302916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.object_bytes += object_bytes;
1303916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.alignment_bytes += alignment_bytes;
1304916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
13052bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    std::ostream& os = *state->os_;
13062dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers    mirror::Class* obj_class = obj->GetClass();
1307d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj_class->IsArrayClass()) {
13082bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p: %s length:%d\n", obj, PrettyDescriptor(obj_class).c_str(),
13092bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         obj->AsArray()->GetLength());
1310d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
13112dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::Class* klass = obj->AsClass();
13122bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p: java.lang.Class \"%s\" (", obj, PrettyDescriptor(klass).c_str())
13132bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers         << klass->GetStatus() << ")\n";
1314ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (obj->IsArtField()) {
13154b8c13ee44c4c959d7b8de9adff7ce6df48c31d0Brian Carlstrom      os << StringPrintf("%p: java.lang.reflect.ArtField %s\n", obj,
1316ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                         PrettyField(obj->AsArtField()).c_str());
1317ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (obj->IsArtMethod()) {
13184b8c13ee44c4c959d7b8de9adff7ce6df48c31d0Brian Carlstrom      os << StringPrintf("%p: java.lang.reflect.ArtMethod %s\n", obj,
1319ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom                         PrettyMethod(obj->AsArtMethod()).c_str());
1320d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj_class->IsStringClass()) {
13212bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p: java.lang.String %s\n", obj,
132268b56858367e29461ae290fd797443a1ef6d8005Ian Rogers                         PrintableString(obj->AsString()->ToModifiedUtf8().c_str()).c_str());
132378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
13242bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("%p: %s\n", obj, PrettyDescriptor(obj_class).c_str());
132578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
13262bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
13272bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    std::ostream indent_os(&indent_filter);
13282bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers    DumpFields(indent_os, obj, obj_class);
1329d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj->IsObjectArray()) {
13302dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers      mirror::ObjectArray<mirror::Object>* obj_array = obj->AsObjectArray<mirror::Object>();
1331d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      int32_t length = obj_array->GetLength();
1332d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < length; i++) {
13332dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers        mirror::Object* value = obj_array->Get(i);
1334d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        size_t run = 0;
1335d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t j = i + 1; j < length; j++) {
1336d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          if (value == obj_array->Get(j)) {
1337d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            run++;
1338d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          } else {
1339d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            break;
1340d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
1341d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
1342d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        if (run == 0) {
13432bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          indent_os << StringPrintf("%d: ", i);
134478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        } else {
13452bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          indent_os << StringPrintf("%d to %zd: ", i, i + run);
1346d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          i = i + run;
134778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        }
13482ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom        mirror::Class* value_class =
13492ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe            (value == nullptr) ? obj_class->GetComponentType() : value->GetClass();
13502bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        PrettyObjectValue(indent_os, value_class, value);
1351d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
1352d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
1353ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ObjectArray<mirror::ArtField>* sfields = obj->AsClass()->GetSFields();
13542ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe      if (sfields != nullptr) {
13552bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        indent_os << "STATICS:\n";
13562bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        Indenter indent2_filter(indent_os.rdbuf(), kIndentChar, kIndentBy1Count);
13572bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        std::ostream indent2_os(&indent2_filter);
1358d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t i = 0; i < sfields->GetLength(); i++) {
1359ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom          mirror::ArtField* field = sfields->Get(i);
13602bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers          PrintField(indent2_os, field, field->GetDeclaringClass());
1361d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
1362d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
1363ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    } else if (obj->IsArtMethod()) {
1364ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom      mirror::ArtMethod* method = obj->AsArtMethod();
1365d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      if (method->IsNative()) {
1366ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        // TODO: portable dumping.
1367ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DCHECK(method->GetNativeGcMap() == nullptr) << PrettyMethod(method);
1368ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        DCHECK(method->GetMappingTable() == nullptr) << PrettyMethod(method);
13693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first_occurrence;
1370ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        const void* quick_oat_code = state->GetQuickOatCodeBegin(method);
1371ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
1372ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        state->ComputeOatSize(quick_oat_code, &first_occurrence);
13733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurrence) {
1374ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          state->stats_.native_to_managed_code_bytes += quick_oat_code_size;
13753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
1376ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        if (quick_oat_code != method->GetEntryPointFromQuickCompiledCode()) {
1377ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          indent_os << StringPrintf("OAT CODE: %p\n", quick_oat_code);
13783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
13791984651929744dd603fd082e23eacd877b9bc177Ian Rogers      } else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
138088474b416eb257078e590bf9bc7957cee604a186Jeff Hao          method->IsResolutionMethod() || method->IsImtConflictMethod() ||
1381bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier          method->IsClassInitializer()) {
13822ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe        DCHECK(method->GetNativeGcMap() == nullptr) << PrettyMethod(method);
13832ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe        DCHECK(method->GetMappingTable() == nullptr) << PrettyMethod(method);
1384916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      } else {
1385bfd9a4378eacaf2dc2bbe05ad48c5164fc93c9feMathieu Chartier        const DexFile::CodeItem* code_item = method->GetCodeItem();
1386d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
1387916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        state->stats_.dex_instruction_bytes += dex_instruction_bytes;
1388e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
1389a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        bool first_occurrence;
13900c7abda482f53db3d153c073d1c7a145f84e0626Ian Rogers        size_t gc_map_bytes = state->ComputeOatSize(method->GetNativeGcMap(), &first_occurrence);
1391a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
13923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.gc_map_bytes += gc_map_bytes;
13933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
13943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
13953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t pc_mapping_table_bytes =
13961809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers            state->ComputeOatSize(method->GetMappingTable(), &first_occurrence);
1397a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
13983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
13993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
14003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
14013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t vmap_table_bytes =
14021809a72a66d245ae598582d658b93a24ac3bf01eIan Rogers            state->ComputeOatSize(method->GetVmapTable(), &first_occurrence);
1403a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
14043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.vmap_table_bytes += vmap_table_bytes;
14053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
14063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1407ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        // TODO: portable dumping.
1408ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        const void* quick_oat_code_begin = state->GetQuickOatCodeBegin(method);
1409ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        const void* quick_oat_code_end = state->GetQuickOatCodeEnd(method);
1410ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        uint32_t quick_oat_code_size = state->GetQuickOatCodeSize(method);
1411ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        state->ComputeOatSize(quick_oat_code_begin, &first_occurrence);
1412a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        if (first_occurrence) {
1413ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers          state->stats_.managed_code_bytes += quick_oat_code_size;
14140d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          if (method->IsConstructor()) {
14150d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            if (method->IsStatic()) {
1416ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers              state->stats_.class_initializer_code_bytes += quick_oat_code_size;
14170d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            } else if (dex_instruction_bytes > kLargeConstructorDexBytes) {
1418ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers              state->stats_.large_initializer_code_bytes += quick_oat_code_size;
14190d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers            }
14200d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          } else if (dex_instruction_bytes > kLargeMethodDexBytes) {
1421ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            state->stats_.large_method_code_bytes += quick_oat_code_size;
14220d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          }
14233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
1424ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        state->stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size;
14253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1426ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers        indent_os << StringPrintf("OAT CODE: %p-%p\n", quick_oat_code_begin, quick_oat_code_end);
14272bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        indent_os << StringPrintf("SIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n",
14282bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes);
14293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
14303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t total_size = dex_instruction_bytes + gc_map_bytes + pc_mapping_table_bytes +
1431ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            vmap_table_bytes + quick_oat_code_size + object_bytes;
14323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
14333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double expansion =
1434ef7d42fca18c16fbaf103822ad16f23246e2905dIan Rogers            static_cast<double>(quick_oat_code_size) / static_cast<double>(dex_instruction_bytes);
14353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        state->stats_.ComputeOutliers(total_size, expansion, method);
143678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      }
143778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
14381ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    std::string temp;
14391ff3c98775a4577cf053dba9a0c2d5c21c07b298Ian Rogers    state->stats_.Update(obj_class->GetDescriptor(&temp), object_bytes);
144078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
144127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
14423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  std::set<const void*> already_seen_;
14433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  // Compute the size of the given data within the oat file and whether this is the first time
14443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  // this data has been requested
1445a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes  size_t ComputeOatSize(const void* oat_data, bool* first_occurrence) {
14463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (already_seen_.count(oat_data) == 0) {
1447a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      *first_occurrence = true;
14483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      already_seen_.insert(oat_data);
14493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    } else {
1450a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      *first_occurrence = false;
14513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
14523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return oat_dumper_->ComputeSize(oat_data);
145327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  }
1454916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1455916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom public:
1456916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  struct Stats {
14573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t oat_file_bytes;
1458916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t file_bytes;
1459916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1460916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t header_bytes;
1461916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes;
146232327098e300ab66671b891a18bf669576fc896aMathieu Chartier    size_t bitmap_bytes;
1463916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes;
1464916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1465916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_code_bytes;
14663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t managed_code_bytes_ignoring_deduplication;
1467916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_to_native_code_bytes;
1468916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t native_to_managed_code_bytes;
14690d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    size_t class_initializer_code_bytes;
14700d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    size_t large_initializer_code_bytes;
14710d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    size_t large_method_code_bytes;
1472916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
14733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t gc_map_bytes;
1474916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t pc_mapping_table_bytes;
14753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t vmap_table_bytes;
1476916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1477916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t dex_instruction_bytes;
1478916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1479ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    std::vector<mirror::ArtMethod*> method_outlier;
14803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::vector<size_t> method_outlier_size;
14813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::vector<double> method_outlier_expansion;
1482700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers    std::vector<std::pair<std::string, size_t>> oat_dex_file_sizes;
14833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
14843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    explicit Stats()
14853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        : oat_file_bytes(0),
14863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          file_bytes(0),
1487916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          header_bytes(0),
1488916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          object_bytes(0),
148932327098e300ab66671b891a18bf669576fc896aMathieu Chartier          bitmap_bytes(0),
1490916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          alignment_bytes(0),
1491916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_code_bytes(0),
14923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          managed_code_bytes_ignoring_deduplication(0),
1493916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_to_native_code_bytes(0),
1494916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          native_to_managed_code_bytes(0),
14950d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          class_initializer_code_bytes(0),
14960d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          large_initializer_code_bytes(0),
14970d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers          large_method_code_bytes(0),
14983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          gc_map_bytes(0),
1499916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          pc_mapping_table_bytes(0),
15003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          vmap_table_bytes(0),
1501916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          dex_instruction_bytes(0) {}
1502916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1503a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    struct SizeAndCount {
1504a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      SizeAndCount(size_t bytes, size_t count) : bytes(bytes), count(count) {}
1505a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      size_t bytes;
1506a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      size_t count;
1507a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    };
1508a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    typedef SafeMap<std::string, SizeAndCount> SizeAndCountTable;
1509a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    SizeAndCountTable sizes_and_counts;
1510a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes
1511fc0e94bed3f88ed7e50854fd8dfaf5dcb345250fIan Rogers    void Update(const char* descriptor, size_t object_bytes) {
1512a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      SizeAndCountTable::iterator it = sizes_and_counts.find(descriptor);
1513a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      if (it != sizes_and_counts.end()) {
1514a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        it->second.bytes += object_bytes;
1515a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        it->second.count += 1;
1516a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      } else {
1517a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes        sizes_and_counts.Put(descriptor, SizeAndCount(object_bytes, 1));
1518a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes      }
1519a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes    }
1520916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
15213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    double PercentOfOatBytes(size_t size) {
15223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100;
15233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
15243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1525916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfFileBytes(size_t size) {
1526916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
1527916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1528916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1529916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfObjectBytes(size_t size) {
1530916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
1531916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1532916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1533ea46f950e7a51585db293cd7f047de190a482414Brian Carlstrom    void ComputeOutliers(size_t total_size, double expansion, mirror::ArtMethod* method) {
15343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier_size.push_back(total_size);
15353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier_expansion.push_back(expansion);
15363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier.push_back(method);
15373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
15383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
153900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    void DumpOutliers(std::ostream& os)
1540b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers        SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
15413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_sizes = 0;
15423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_sizes_squared = 0;
15433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_expansion = 0;
15443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_expansion_squared = 0;
15453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t n = method_outlier_size.size();
15463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 0; i < n; i++) {
15473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t cur_size = method_outlier_size[i];
15483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_sizes += cur_size;
15493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_sizes_squared += cur_size * cur_size;
15503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double cur_expansion = method_outlier_expansion[i];
15513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_expansion += cur_expansion;
15523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_expansion_squared += cur_expansion * cur_expansion;
15533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
15543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t size_mean = sum_of_sizes / n;
15553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t size_variance = (sum_of_sizes_squared - sum_of_sizes * size_mean) / (n - 1);
15563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      double expansion_mean = sum_of_expansion / n;
15573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      double expansion_variance =
15583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          (sum_of_expansion_squared - sum_of_expansion * expansion_mean) / (n - 1);
15593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
15603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      // Dump methods whose size is a certain number of standard deviations from the mean
15613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t dumped_values = 0;
15623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t skipped_values = 0;
15633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 100; i > 0; i--) {  // i is the current number of standard deviations
15643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t cur_size_variance = i * i * size_variance;
15653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first = true;
15663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        for (size_t j = 0; j < n; j++) {
15673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          size_t cur_size = method_outlier_size[j];
15683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (cur_size > size_mean) {
15693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            size_t cur_var = cur_size - size_mean;
15703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            cur_var = cur_var * cur_var;
15713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            if (cur_var > cur_size_variance) {
15723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              if (dumped_values > 20) {
15733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (i == 1) {
15743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  skipped_values++;
15753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                } else {
15763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  i = 2;  // jump to counting for 1 standard deviation
15773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  break;
15783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
15793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              } else {
15803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (first) {
1581c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                  os << "\nBig methods (size > " << i << " standard deviations the norm):\n";
15823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  first = false;
15833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
15842bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                os << PrettyMethod(method_outlier[j]) << " requires storage of "
1585c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                    << PrettySize(cur_size) << "\n";
15863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                method_outlier_size[j] = 0;  // don't consider this method again
15873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                dumped_values++;
15883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              }
15893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            }
15903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
15913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
15923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
15933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (skipped_values > 0) {
15942bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << "... skipped " << skipped_values
1595c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes           << " methods with size > 1 standard deviation from the norm\n";
15963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
1597c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << std::flush;
15983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
15993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      // Dump methods whose expansion is a certain number of standard deviations from the mean
16003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      dumped_values = 0;
16013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      skipped_values = 0;
16023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 10; i > 0; i--) {  // i is the current number of standard deviations
16033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double cur_expansion_variance = i * i * expansion_variance;
16043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first = true;
16053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        for (size_t j = 0; j < n; j++) {
16063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          double cur_expansion = method_outlier_expansion[j];
16073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (cur_expansion > expansion_mean) {
16083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            size_t cur_var = cur_expansion - expansion_mean;
16093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            cur_var = cur_var * cur_var;
16103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            if (cur_var > cur_expansion_variance) {
16113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              if (dumped_values > 20) {
16123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (i == 1) {
16133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  skipped_values++;
16143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                } else {
16153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  i = 2;  // jump to counting for 1 standard deviation
16163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  break;
16173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
16183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              } else {
16193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (first) {
16203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  os << "\nLarge expansion methods (size > " << i
1621c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                      << " standard deviations the norm):\n";
16223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  first = false;
16233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
16242bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                os << PrettyMethod(method_outlier[j]) << " expanded code by "
1625c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                   << cur_expansion << "\n";
16263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                method_outlier_expansion[j] = 0.0;  // don't consider this method again
16273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                dumped_values++;
16283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              }
16293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            }
16303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
16313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
16323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
16333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (skipped_values > 0) {
16342bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << "... skipped " << skipped_values
1635c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes           << " methods with expansion > 1 standard deviation from the norm\n";
16363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
1637c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << "\n" << std::flush;
16383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
16393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1640b726dcb581bf72da46527378ccb6889020f0e6e9Ian Rogers    void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
16412bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      {
16422bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << "art_file_bytes = " << PrettySize(file_bytes) << "\n\n"
16432bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers           << "art_file_bytes = header_bytes + object_bytes + alignment_bytes\n";
16442bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        Indenter indent_filter(os.rdbuf(), kIndentChar, kIndentBy1Count);
16452bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        std::ostream indent_os(&indent_filter);
16462bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        indent_os << StringPrintf("header_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
16472bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  "object_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
164832327098e300ab66671b891a18bf669576fc896aMathieu Chartier                                  "bitmap_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
16492bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  "alignment_bytes =  %8zd (%2.0f%% of art file bytes)\n\n",
16502bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  header_bytes, PercentOfFileBytes(header_bytes),
16512bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  object_bytes, PercentOfFileBytes(object_bytes),
165232327098e300ab66671b891a18bf669576fc896aMathieu Chartier                                  bitmap_bytes, PercentOfFileBytes(bitmap_bytes),
16532bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                  alignment_bytes, PercentOfFileBytes(alignment_bytes))
16542bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            << std::flush;
165532327098e300ab66671b891a18bf669576fc896aMathieu Chartier        CHECK_EQ(file_bytes, bitmap_bytes + header_bytes + object_bytes + alignment_bytes);
16562bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      }
1657916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
16582bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "object_bytes breakdown:\n";
1659916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      size_t object_bytes_total = 0;
166002e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      for (const auto& sizes_and_count : sizes_and_counts) {
166102e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier        const std::string& descriptor(sizes_and_count.first);
166202e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier        double average = static_cast<double>(sizes_and_count.second.bytes) /
166302e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier            static_cast<double>(sizes_and_count.second.count);
166402e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier        double percent = PercentOfObjectBytes(sizes_and_count.second.bytes);
16652bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%32s %8zd bytes %6zd instances "
1666a0e180632411f7fe0edf454e571c42209ee7b540Elliott Hughes                           "(%4.0f bytes/instance) %2.0f%% of object_bytes\n",
166702e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                           descriptor.c_str(), sizes_and_count.second.bytes,
166802e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                           sizes_and_count.second.count, average, percent);
166902e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier        object_bytes_total += sizes_and_count.second.bytes;
1670916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      }
1671c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes      os << "\n" << std::flush;
1672916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(object_bytes, object_bytes_total);
1673916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
16742bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("oat_file_bytes               = %8zd\n"
16752bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "managed_code_bytes           = %8zd (%2.0f%% of oat file bytes)\n"
16762bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "managed_to_native_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
16772bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "native_to_managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n\n"
16782bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "class_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
16792bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "large_initializer_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
16802bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                         "large_method_code_bytes      = %8zd (%2.0f%% of oat file bytes)\n\n",
168105f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers                         oat_file_bytes,
16822ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         managed_code_bytes,
16832ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(managed_code_bytes),
16842ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         managed_to_native_code_bytes,
16852ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(managed_to_native_code_bytes),
16862ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         native_to_managed_code_bytes,
16872ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(native_to_managed_code_bytes),
16882ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         class_initializer_code_bytes,
16892ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(class_initializer_code_bytes),
16902ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         large_initializer_code_bytes,
16912ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(large_initializer_code_bytes),
16922ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         large_method_code_bytes,
16932ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         PercentOfOatBytes(large_method_code_bytes))
16942bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers            << "DexFile sizes:\n";
169502e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier      for (const std::pair<std::string, size_t>& oat_dex_file_size : oat_dex_file_sizes) {
16962bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers        os << StringPrintf("%s = %zd (%2.0f%% of oat file bytes)\n",
169702e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                           oat_dex_file_size.first.c_str(), oat_dex_file_size.second,
169802e25119b15a6f619f17db99f5d05124a5807ff3Mathieu Chartier                           PercentOfOatBytes(oat_dex_file_size.second));
169905f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers      }
170005f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers
17012bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << "\n" << StringPrintf("gc_map_bytes           = %7zd (%2.0f%% of oat file bytes)\n"
17022bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                 "pc_mapping_table_bytes = %7zd (%2.0f%% of oat file bytes)\n"
17032bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers                                 "vmap_table_bytes       = %7zd (%2.0f%% of oat file bytes)\n\n",
170405f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers                                 gc_map_bytes, PercentOfOatBytes(gc_map_bytes),
170505f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers                                 pc_mapping_table_bytes, PercentOfOatBytes(pc_mapping_table_bytes),
170605f28c6e00ecdb1da834acc8c29b4a7eba86d692Ian Rogers                                 vmap_table_bytes, PercentOfOatBytes(vmap_table_bytes))
1707c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << std::flush;
1708916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
17092bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers      os << StringPrintf("dex_instruction_bytes = %zd\n", dex_instruction_bytes)
17102bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers         << StringPrintf("managed_code_bytes expansion = %.2f (ignoring deduplication %.2f)\n\n",
17112ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                         static_cast<double>(managed_code_bytes) /
17122ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                             static_cast<double>(dex_instruction_bytes),
1713c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes                         static_cast<double>(managed_code_bytes_ignoring_deduplication) /
1714cf44e6f1ec194a906f4760a7c0395fdb0123d7aeElliott Hughes                             static_cast<double>(dex_instruction_bytes))
1715c073b075241640c94c27e661ed6f29ff5fcee5d8Elliott Hughes         << std::flush;
17163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
17173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOutliers(os);
1718916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1719916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  } stats_;
1720916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1721916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom private:
17220d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers  enum {
17230d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // Number of bytes for a constructor to be considered large. Based on the 1000 basic block
17240d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // threshold, we assume 2 bytes per instruction and 2 instructions per block.
17250d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    kLargeConstructorDexBytes = 4000,
17260d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // Number of bytes for a method to be considered large. Based on the 4000 basic block
17270d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    // threshold, we assume 2 bytes per instruction and 2 instructions per block.
17280d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers    kLargeMethodDexBytes = 16000
17290d2d3785961d8d542cba68a8e9126b01d3102f64Ian Rogers  };
1730700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<OatDumper> oat_dumper_;
17312bcb4a496b7aa00d996df3a070524f7568fb35a1Ian Rogers  std::ostream* os_;
17321d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  gc::space::ImageSpace& image_space_;
17333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const ImageHeader& image_header_;
1734404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_mapping_table_;
1735404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_gc_map_;
1736d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
17373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  DISALLOW_COPY_AND_ASSIGN(ImageDumper);
173878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
173978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
174072395bf298b7707ad9d93c3e51b57e1b8e010311Elliott Hughesstatic int oatdump(int argc, char** argv) {
17410d39c12238499ca9ccc34d1532c443335e7c1044Elliott Hughes  InitLogging(argv);
174272395bf298b7707ad9d93c3e51b57e1b8e010311Elliott Hughes
174378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  // Skip over argv[0].
174478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argv++;
174578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argc--;
174678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
174778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (argc == 0) {
1748aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "No arguments specified\n");
174978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    usage();
175078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
175178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
17522ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  const char* oat_filename = nullptr;
17532ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  const char* image_location = nullptr;
17542ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  const char* boot_image_location = nullptr;
17550f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  InstructionSet instruction_set = kRuntimeISA;
17560cc6ab6c5104f565a0a3256b5b2b31c6383be189Logan Chien  std::string elf_filename_prefix;
175727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream* os = &std::cout;
1758700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<std::ofstream> out;
175954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  std::string output_name;
1760404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_mapping_table = false;
1761404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison  bool dump_raw_gc_map = false;
176254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe  bool symbolize = false;
176378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
176478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  for (int i = 0; i < argc; i++) {
176578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    const StringPiece option(argv[i]);
1766a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    if (option.starts_with("--oat-file=")) {
1767a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      oat_filename = option.substr(strlen("--oat-file=")).data();
1768aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    } else if (option.starts_with("--image=")) {
17690f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      image_location = option.substr(strlen("--image=")).data();
1770e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    } else if (option.starts_with("--boot-image=")) {
17710f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      boot_image_location = option.substr(strlen("--boot-image=")).data();
17720f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom    } else if (option.starts_with("--instruction-set=")) {
17730f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      StringPiece instruction_set_str = option.substr(strlen("--instruction-set=")).data();
17740f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      if (instruction_set_str == "arm") {
17750f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kThumb2;
17760f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      } else if (instruction_set_str == "arm64") {
17770f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kArm64;
17780f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      } else if (instruction_set_str == "mips") {
17790f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kMips;
17800f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      } else if (instruction_set_str == "x86") {
17810f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kX86;
17820f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      } else if (instruction_set_str == "x86_64") {
17830f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom        instruction_set = kX86_64;
17840f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      }
1785404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison    } else if (option.starts_with("--dump:")) {
1786404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        if (option == "--dump:raw_mapping_table") {
1787404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          dump_raw_mapping_table = true;
1788404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        } else if (option == "--dump:raw_gc_map") {
1789404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          dump_raw_gc_map = true;
1790404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        } else {
1791404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          fprintf(stderr, "Unknown argument %s\n", option.data());
1792404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison          usage();
1793404f59f4125ec9935ad8cffac56ab99d6320b17bDave Allison        }
179427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    } else if (option.starts_with("--output=")) {
179554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      output_name = option.substr(strlen("--output=")).ToString();
179654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      const char* filename = output_name.c_str();
179727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      out.reset(new std::ofstream(filename));
179827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      if (!out->good()) {
1799aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom        fprintf(stderr, "Failed to open output filename %s\n", filename);
180027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        usage();
180127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      }
180227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      os = out.get();
180354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    } else if (option.starts_with("--symbolize=")) {
180454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      oat_filename = option.substr(strlen("--symbolize=")).data();
180554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      symbolize = true;
180678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
1807aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Unknown argument %s\n", option.data());
180878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      usage();
180978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
181078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
181178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
18122ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  if (image_location == nullptr && oat_filename == nullptr) {
1813362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified\n");
1814362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
181578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
181678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
18172ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  if (image_location != nullptr && oat_filename != nullptr) {
1818362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified but not both\n");
1819362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
1820aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
1821aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
18222ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  if (oat_filename != nullptr) {
18238d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers    std::string error_msg;
18240c717dd1c56bd29cf860d0feda8e629dab2cadb3Logan Chien    OatFile* oat_file =
18252ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe        OatFile::Open(oat_filename, oat_filename, nullptr, false, &error_msg);
18262ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    if (oat_file == nullptr) {
18278d31bbd3d6536de12bc20e3d29cfe03fe848f9daIan Rogers      fprintf(stderr, "Failed to open oat file from '%s': %s\n", oat_filename, error_msg.c_str());
1828aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return EXIT_FAILURE;
1829aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
183054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    if (symbolize) {
183154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      OatSymbolizer oat_symbolizer(oat_file, output_name);
183254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      if (!oat_symbolizer.Init()) {
183354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        fprintf(stderr, "Failed to initialize symbolizer\n");
183454fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        return EXIT_FAILURE;
183554fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      }
183654fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      if (!oat_symbolizer.Symbolize()) {
183754fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        fprintf(stderr, "Failed to symbolize\n");
183854fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe        return EXIT_FAILURE;
183954fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      }
184054fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    } else {
184154fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      OatDumper oat_dumper(*oat_file, dump_raw_mapping_table, dump_raw_gc_map);
184254fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe      oat_dumper.Dump(*os);
184354fc26c7350beb782d042ba61cb06284b3a367e4Andreas Gampe    }
1844aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return EXIT_SUCCESS;
1845aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
1846aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
1847e63db27db913f1a88e2095a1ee8239b2bb9124e8Ian Rogers  RuntimeOptions options;
184878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string image_option;
1849e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string oat_option;
185078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string boot_image_option;
1851e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string boot_oat_option;
18526c87180aef7d3127c0f25fcbc76e71f4a4f2b9faBrian Carlstrom
18536c87180aef7d3127c0f25fcbc76e71f4a4f2b9faBrian Carlstrom  // We are more like a compiler than a run-time. We don't want to execute code.
1854c0a1b18ac71ec0ff3ec0cca3cc8db9eb74e50690Brian Carlstrom  NoopCompilerCallbacks callbacks;
1855c0a1b18ac71ec0ff3ec0cca3cc8db9eb74e50690Brian Carlstrom  options.push_back(std::make_pair("compilercallbacks", &callbacks));
18566c87180aef7d3127c0f25fcbc76e71f4a4f2b9faBrian Carlstrom
18572ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  if (boot_image_location != nullptr) {
185858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += "-Ximage:";
18590f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom    boot_image_option += boot_image_location;
18602ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    options.push_back(std::make_pair(boot_image_option.c_str(), nullptr));
186158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
18622ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  if (image_location != nullptr) {
1863aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += "-Ximage:";
18640f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom    image_option += image_location;
18652ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe    options.push_back(std::make_pair(image_option.c_str(), nullptr));
1866aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
18670f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom  options.push_back(
18680f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom      std::make_pair("imageinstructionset",
18690f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom                     reinterpret_cast<const void*>(GetInstructionSetString(instruction_set))));
187058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
187100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  if (!Runtime::Create(options, false)) {
1872aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Failed to create runtime\n");
187378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
187478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
1875700a402244a1a423da4f3ba8032459f4b65fa18fIan Rogers  std::unique_ptr<Runtime> runtime(Runtime::Current());
187600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  // Runtime::Create acquired the mutator_lock_ that is normally given away when we Runtime::Start,
1877b9beb2e2efb6a204a69ca660d478b45f851e8f09Ian Rogers  // give it away now and then switch to a more manageable ScopedObjectAccess.
187800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
187900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers  ScopedObjectAccess soa(Thread::Current());
18801d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  gc::Heap* heap = Runtime::Current()->GetHeap();
18811d54e73444e017d3a65234e0f193846f3e27472bIan Rogers  gc::space::ImageSpace* image_space = heap->GetImageSpace();
18822ed8deff799448e094fa7a7cb9cf3b718820f4c6Andreas Gampe  CHECK(image_space != nullptr);
188378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const ImageHeader& image_header = image_space->GetImageHeader();
188478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (!image_header.IsValid()) {
18850f5baa079eea76758aee32d7f87cb175deab8308Brian Carlstrom    fprintf(stderr, "Invalid image header %s\n", image_location);
188678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
188778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
18882ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom  ImageDumper image_dumper(os, *image_space, image_header,
18892ec6520d57479d393bffa05defa1479b25ca8382Brian Carlstrom                           dump_raw_mapping_table, dump_raw_gc_map);
18903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  image_dumper.Dump();
189178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return EXIT_SUCCESS;
189278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
189378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
18947934ac288acfb2552bb0b06ec1f61e5820d924a4Brian Carlstrom}  // namespace art
189578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
189678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint main(int argc, char** argv) {
189778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return art::oatdump(argc, argv);
189878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
1899