oatdump.cc revision 81f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bc
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>
22e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes#include <map>
2378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <string>
2478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <vector>
2578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
2678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "class_linker.h"
273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers#include "context.h"
28e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes#include "dex_instruction.h"
293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers#include "dex_verifier.h"
303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers#include "disassembler.h"
31916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom#include "file.h"
3278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "image.h"
336d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
34e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes#include "os.h"
3578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "runtime.h"
3678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "space.h"
3778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "stringpiece.h"
3878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
3978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromnamespace art {
4078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
4178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromstatic void usage() {
4278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
4378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "Usage: oatdump [options] ...\n"
4429e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "    Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art --host-prefix=$ANDROID_PRODUCT_OUT\n"
4529e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "    Example: adb shell oatdump --image=/system/framework/boot.art\n"
4678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "\n");
4778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
48a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "  --oat-file=<file.oat>: specifies an input oat filename.\n"
4929e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --image=/system/framework/boot.oat\n"
50aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom          "\n");
51aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  fprintf(stderr,
52aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom          "  --image=<file.art>: specifies an input image filename.\n"
5329e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --image=/system/framework/boot.art\n"
54e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
5578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
56e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "  --boot-image=<file.art>: provide the image file for the boot class path.\n"
5729e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --boot-image=/system/framework/boot.art\n"
58e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
59e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  fprintf(stderr,
6058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "  --host-prefix may be used to translate host paths to target paths during\n"
6158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "      cross compilation.\n"
6258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "      Example: --host-prefix=out/target/product/crespo\n"
63fe487d0c789b94e75c93a2b799f1955c3e4edb10Brian Carlstrom          "      Default: $ANDROID_PRODUCT_OUT\n"
6478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "\n");
6527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  fprintf(stderr,
6627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "  --output=<file> may be used to send the output to a file.\n"
6727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "      Example: --output=/tmp/oatdump.txt\n"
6827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "\n");
6978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  exit(EXIT_FAILURE);
7078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
7178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
72ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogersconst char* image_roots_descriptions_[] = {
7378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  "kJniStubArray",
74e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kAbstractMethodErrorStubArray",
75ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  "kStaticResolutionStubArray",
761cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  "kUnknownMethodResolutionStubArray",
771984651929744dd603fd082e23eacd877b9bc177Ian Rogers  "kResolutionMethod",
78e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kCalleeSaveMethod",
79aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  "kRefsOnlySaveMethod",
80aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  "kRefsAndArgsSaveMethod",
81e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kOatLocation",
8258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  "kDexCaches",
8334f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom  "kClassRoots",
8478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
8578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
86e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughesclass OatDumper {
87aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom public:
8881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  explicit OatDumper(const std::string& host_prefix, const OatFile& oat_file)
8981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    : host_prefix_(host_prefix),
9081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom      oat_file_(oat_file),
91a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes      oat_dex_files_(oat_file.GetOatDexFiles()),
92a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes      disassembler_(Disassembler::Create(oat_file_.GetOatHeader().GetInstructionSet())) {
933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    AddAllOffsets();
943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void Dump(std::ostream& os) {
973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    const OatHeader& oat_header = oat_file_.GetOatHeader();
98aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
99aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "MAGIC:\n";
100aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetMagic() << "\n\n";
101aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
102aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "CHECKSUM:\n";
103ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("0x%08x\n\n", oat_header.GetChecksum());
104aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
105a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes    os << "INSTRUCTION SET:\n";
106a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes    os << oat_header.GetInstructionSet() << "\n\n";
107a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes
108aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "DEX FILE COUNT:\n";
109aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetDexFileCount() << "\n\n";
110aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
111aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "EXECUTABLE OFFSET:\n";
112ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset());
113aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
11481f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << "IMAGE FILE LOCATION CHECKSUM:\n";
11581f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationChecksum());
11681f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
11781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << "IMAGE FILE LOCATION:\n";
11881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    const std::string image_file_location(oat_header.GetImageFileLocation());
11981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << image_file_location;
12081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    if (!image_file_location.empty() && !host_prefix_.empty()) {
12181f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom      os << " (" << host_prefix_ << image_file_location << ")";
12281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    }
12381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    os << "\n\n";
12481f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
12530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "BEGIN:\n";
1263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << reinterpret_cast<const void*>(oat_file_.Begin()) << "\n\n";
127aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
12830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "END:\n";
1293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << reinterpret_cast<const void*>(oat_file_.End()) << "\n\n";
130aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
131aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
132aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
1333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
1343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
1353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      CHECK(oat_dex_file != NULL);
1363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOatDexFile(os, *oat_dex_file);
1373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
1383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
1393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  size_t ComputeSize(const void* oat_data) {
1413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (reinterpret_cast<const byte*>(oat_data) < oat_file_.Begin() ||
1423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        reinterpret_cast<const byte*>(oat_data) > oat_file_.End()) {
1433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return 0;  // Address not in oat file
1443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
1453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    uint32_t begin_offset = reinterpret_cast<size_t>(oat_data) -
1463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                            reinterpret_cast<size_t>(oat_file_.Begin());
1473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    typedef std::set<uint32_t>::iterator It;
1483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    It it = offsets_.upper_bound(begin_offset);
1493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    CHECK(it != offsets_.end());
1503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    uint32_t end_offset = *it;
1513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return end_offset - begin_offset;
1523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
153e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
154f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  InstructionSet GetInstructionSet() {
155f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    return oat_file_.GetOatHeader().GetInstructionSet();
156f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
157f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
1583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const void* GetOatCode(Method* m) {
1593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    MethodHelper mh(m);
1603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
1613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
162aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CHECK(oat_dex_file != NULL);
1633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      UniquePtr<const DexFile> dex_file(oat_dex_file->OpenDexFile());
1643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (dex_file.get() != NULL) {
1653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        uint32_t class_def_index;
1663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool found = dex_file->FindClassDefIndex(mh.GetDeclaringClassDescriptor(), class_def_index);
1673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (found) {
1683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          const OatFile::OatClass* oat_class = oat_dex_file->GetOatClass(class_def_index);
1693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          CHECK(oat_class != NULL);
1703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          size_t method_index = m->GetMethodIndex();
1713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          return oat_class->GetOatMethod(method_index).GetCode();
1723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
1733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
174aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
1753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return NULL;
176aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
177aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
178aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom private:
1793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void AddAllOffsets() {
180e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // We don't know the length of the code for each method, but we need to know where to stop
181e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // when disassembling. What we do know is that a region of code will be followed by some other
182e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // region, so if we keep a sorted sequence of the start of each region, we can infer the length
183e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // of a piece of code by using upper_bound to find the start of the next region.
1843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < oat_dex_files_.size(); i++) {
1853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
186e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      CHECK(oat_dex_file != NULL);
187e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      UniquePtr<const DexFile> dex_file(oat_dex_file->OpenDexFile());
188e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      if (dex_file.get() == NULL) {
1893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        continue;
190e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
1913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      offsets_.insert(reinterpret_cast<uint32_t>(&dex_file->GetHeader()));
192e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) {
193e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
194e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index));
195e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        const byte* class_data = dex_file->GetClassData(class_def);
196e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        if (class_data != NULL) {
197e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          ClassDataItemIterator it(*dex_file, class_data);
198e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          SkipAllFields(it);
199e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          uint32_t class_method_index = 0;
200e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          while (it.HasNextDirectMethod()) {
201e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            AddOffsets(oat_class->GetOatMethod(class_method_index++));
202e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            it.Next();
203e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          }
204e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          while (it.HasNextVirtualMethod()) {
205e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            AddOffsets(oat_class->GetOatMethod(class_method_index++));
206e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes            it.Next();
207e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes          }
208e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        }
209e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
210e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
211e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
212e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // If the last thing in the file is code for a method, there won't be an offset for the "next"
213e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // thing. Instead of having a special case in the upper_bound code, let's just add an entry
214e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    // for the end of the file.
2153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    offsets_.insert(static_cast<uint32_t>(oat_file_.End() - oat_file_.Begin()));
216e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
217e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
218e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  void AddOffsets(const OatFile::OatMethod& oat_method) {
21995ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    uint32_t code_offset = oat_method.GetCodeOffset();
22095ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    if (oat_file_.GetOatHeader().GetInstructionSet() == kThumb2) {
22195ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom      code_offset &= ~0x1;
22295ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    }
22395ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom    offsets_.insert(code_offset);
224e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    offsets_.insert(oat_method.GetMappingTableOffset());
225e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    offsets_.insert(oat_method.GetVmapTableOffset());
226e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    offsets_.insert(oat_method.GetGcMapOffset());
227e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    offsets_.insert(oat_method.GetInvokeStubOffset());
228e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
229e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
2303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpOatDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) {
231aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "OAT DEX FILE:\n";
232a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str());
233ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("checksum: 0x%08x\n", oat_dex_file.GetDexFileLocationChecksum());
234a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    UniquePtr<const DexFile> dex_file(oat_dex_file.OpenDexFile());
235a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    if (dex_file.get() == NULL) {
236aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      os << "NOT FOUND\n\n";
237aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return;
238aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
239aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) {
240aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
241aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const char* descriptor = dex_file->GetClassDescriptor(class_def);
242aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file.GetOatClass(class_def_index));
243aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CHECK(oat_class.get() != NULL);
244ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("%zd: %s (type_idx=%d) (", class_def_index, descriptor, class_def.class_idx_)
245e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom         << oat_class->GetStatus() << ")\n";
2463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOatClass(os, *oat_class.get(), *(dex_file.get()), class_def);
247aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
248aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
249aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
250aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
251aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
252e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  static void SkipAllFields(ClassDataItemIterator& it) {
2530571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextStaticField()) {
2540571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
255aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
2560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextInstanceField()) {
2570571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
258aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
259e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
260aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
2613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpOatClass(std::ostream& os, const OatFile::OatClass& oat_class, const DexFile& dex_file,
2623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                    const DexFile::ClassDef& class_def) {
263e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    const byte* class_data = dex_file.GetClassData(class_def);
264e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    if (class_data == NULL) {  // empty class such as a marker interface?
265e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      return;
266e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
267e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    ClassDataItemIterator it(dex_file, class_data);
268e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    SkipAllFields(it);
269e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
270e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    uint32_t class_method_index = 0;
2710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextDirectMethod()) {
272e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_index);
2733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOatMethod(os, class_method_index, oat_method, dex_file,
2743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                    it.GetMemberIndex(), it.GetMethodCodeItem());
275e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      class_method_index++;
2760571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
277aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
2780571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextVirtualMethod()) {
279e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_index);
2803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOatMethod(os, class_method_index, oat_method, dex_file,
2813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                    it.GetMemberIndex(), it.GetMethodCodeItem());
282e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      class_method_index++;
2830571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
284aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
2850571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    DCHECK(!it.HasNext());
286aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
287aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
288e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
2893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpOatMethod(std::ostream& os, uint32_t class_method_index,
290e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes                     const OatFile::OatMethod& oat_method, const DexFile& dex_file,
291e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes                     uint32_t dex_method_idx, const DexFile::CodeItem* code_item) {
292e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx);
293aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    const char* name = dex_file.GetMethodName(method_id);
294955724179c6c739524f610023287f56b24dc31deElliott Hughes    std::string signature(dex_file.GetMethodSignature(method_id));
295e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    os << StringPrintf("\t%d: %s %s (dex_method_idx=%d)\n",
296e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes                       class_method_index, name, signature.c_str(), dex_method_idx);
297ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes    os << StringPrintf("\t\tframe_size_in_bytes: %zd\n",
298ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetFrameSizeInBytes());
2993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << StringPrintf("\t\tcore_spill_mask: 0x%08x",
300ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetCoreSpillMask());
3013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DumpSpillMask(os, oat_method.GetCoreSpillMask(), false);
3023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << StringPrintf("\n\t\tfp_spill_mask: 0x%08x",
303ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetFpSpillMask());
3043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DumpSpillMask(os, oat_method.GetFpSpillMask(), true);
3053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << StringPrintf("\n\t\tmapping_table: %p (offset=0x%08x)\n",
306ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetMappingTable(), oat_method.GetMappingTableOffset());
3073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DumpMappingTable(os, oat_method);
308ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("\t\tvmap_table: %p (offset=0x%08x)\n",
309ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetVmapTable(), oat_method.GetVmapTableOffset());
3103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DumpVmap(os, oat_method.GetVmapTable(), oat_method.GetCoreSpillMask(),
3113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers             oat_method.GetFpSpillMask());
312ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes    os << StringPrintf("\t\tgc_map: %p (offset=0x%08x)\n",
313e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                       oat_method.GetGcMap(), oat_method.GetGcMapOffset());
3143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DumpGcMap(os, oat_method.GetGcMap());
31577405796564c6c1353807cda18b28678a719bd68Elliott Hughes    os << StringPrintf("\t\tCODE: %p (offset=0x%08x size=%d)%s\n",
31677405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetCode(),
31777405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetCodeOffset(),
31877405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetCodeSize(),
31977405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetCode() != NULL ? "..." : "");
3203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DumpCode(os, oat_method.GetCode(), oat_method.GetMappingTable(), dex_file, code_item);
32177405796564c6c1353807cda18b28678a719bd68Elliott Hughes    os << StringPrintf("\t\tINVOKE STUB: %p (offset=0x%08x size=%d)%s\n",
32277405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetInvokeStub(),
32377405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetInvokeStubOffset(),
32477405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetInvokeStubSize(),
32577405796564c6c1353807cda18b28678a719bd68Elliott Hughes                       oat_method.GetInvokeStub() != NULL ? "..." : "");
3263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DumpCode(os, reinterpret_cast<const void*>(oat_method.GetInvokeStub()), NULL, dex_file, NULL);
3273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
3283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
3293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpSpillMask(std::ostream& os, uint32_t spill_mask, bool is_float) {
3303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (spill_mask == 0) {
3313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
3323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
3333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << " (";
3343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < 32; i++) {
3353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if ((spill_mask & (1 << i)) != 0) {
3363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (is_float) {
3373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << "fr" << i;
3383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        } else {
3393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << "r" << i;
3403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
3413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        spill_mask ^= 1 << i;  // clear bit
3423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (spill_mask != 0) {
3433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          os << ", ";
3443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        } else {
3453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          break;
3463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
3473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
3483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
3493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << ")";
3503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
3513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
3523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpVmap(std::ostream& os, const uint16_t* raw_table, uint32_t core_spill_mask,
3533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                uint32_t fp_spill_mask) {
3543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (raw_table == NULL) {
3553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
3563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
3573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    const VmapTable vmap_table(raw_table);
3583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    bool first = true;
3593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << "\t\t\t";
3603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < vmap_table.size(); i++) {
3613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      uint16_t dex_reg = vmap_table[i];
3623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t matches = 0;
3633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t spill_shifts = 0;
3643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      uint32_t spill_mask = core_spill_mask;
3653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      bool processing_fp = false;
3663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      while (matches != (i + 1)) {
3673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (spill_mask == 0) {
3683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          CHECK(!processing_fp);
3693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          spill_mask = fp_spill_mask;
3703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          processing_fp = true;
3713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
3723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        matches += spill_mask & 1;  // Add 1 if the low bit is set
3733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        spill_mask >>= 1;
3743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        spill_shifts++;
3753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
3763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t arm_reg = spill_shifts - 1;  // wind back one as we want the last match
3773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << (first ? "v" : ", v")  << dex_reg;
3783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (arm_reg < 16) {
3793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << "/r" << arm_reg;
3803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      } else {
3813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << "/fr" << (arm_reg - 16);
3823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
3833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (first) {
3843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        first = false;
3853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
3863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
3873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << std::endl;
3883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
3893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
3903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpGcMap(std::ostream& os, const uint8_t* gc_map_raw) {
3913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (gc_map_raw == NULL) {
3923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
3933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
3943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    uint32_t gc_map_length = (gc_map_raw[0] << 24) | (gc_map_raw[1] << 16) |
3953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                             (gc_map_raw[2] << 8) | (gc_map_raw[3] << 0);
3963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    verifier::PcToReferenceMap map(gc_map_raw + sizeof(uint32_t), gc_map_length);
3973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t entry = 0; entry < map.NumEntries(); entry++) {
3983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << StringPrintf("\t\t\t0x%04x", map.GetPC(entry));
3993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t num_regs = map.RegWidth() * 8;
4003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const uint8_t* reg_bitmap = map.GetBitMap(entry);
4013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      bool first = true;
4023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t reg = 0; reg < num_regs; reg++) {
4033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) {
4043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (first) {
4053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            os << "  v" << reg;
4063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            first = false;
4073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          } else {
4083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            os << ", v" << reg;
4093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
4103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
4113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
4123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << std::endl;
4133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
414aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
415e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
4163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpMappingTable(std::ostream& os, const OatFile::OatMethod& oat_method) {
417e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    const uint32_t* raw_table = oat_method.GetMappingTable();
418e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    const void* code = oat_method.GetCode();
419e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    if (raw_table == NULL || code == NULL) {
420e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      return;
421e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
422e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
423e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    uint32_t length = *raw_table;
424e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    ++raw_table;
425e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
4263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << "\t\t{";
427e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    for (size_t i = 0; i < length; i += 2) {
4283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code) + raw_table[i];
429e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      uint32_t dex_pc = raw_table[i + 1];
4303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << StringPrintf("%p -> 0x%04x", native_pc, dex_pc);
4313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (i + 2 < length) {
4323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << ", ";
4333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
4343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
4353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os << "}" << std::endl << std::flush;
4363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
4373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
4383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void DumpCode(std::ostream& os, const void* code, const uint32_t* raw_mapping_table,
4393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                const DexFile& dex_file, const DexFile::CodeItem* code_item) {
4403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (code == NULL) {
4413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
4423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
4433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
4443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (raw_mapping_table == NULL) {
4453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      // code but no mapping table is most likely caused by code created by the JNI compiler
4463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code);
4473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const uint8_t* oat_begin = reinterpret_cast<const uint8_t*>(oat_file_.Begin());
4483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      uint32_t last_offset = static_cast<uint32_t>(native_pc - oat_begin);
4493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
4503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      typedef std::set<uint32_t>::iterator It;
4513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      It it = offsets_.upper_bound(last_offset);
4523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      CHECK(it != offsets_.end());
4533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const uint8_t* end_native_pc = reinterpret_cast<const uint8_t*>(oat_begin) + *it;
4543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      CHECK(native_pc < end_native_pc);
4553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
4563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      disassembler_->Dump(os, native_pc, end_native_pc);
4573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return;
4583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
4593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
4603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    uint32_t length = *raw_mapping_table;
4613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    ++raw_mapping_table;
4623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
4633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    for (size_t i = 0; i < length; i += 2) {
4643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      uint32_t dex_pc = raw_mapping_table[i + 1];
465e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      const Instruction* instruction = Instruction::At(&code_item->insns_[dex_pc]);
466e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      os << StringPrintf("\t\t0x%04x: %s\n", dex_pc, instruction->DumpString(&dex_file).c_str());
467e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
4683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code) + raw_mapping_table[i];
469e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      const uint8_t* end_native_pc = NULL;
470e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      if (i + 2 < length) {
4713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        end_native_pc = reinterpret_cast<const uint8_t*>(code) + raw_mapping_table[i + 2];
472e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      } else {
4733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        const uint8_t* oat_begin = reinterpret_cast<const uint8_t*>(oat_file_.Begin());
474e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        uint32_t last_offset = static_cast<uint32_t>(native_pc - oat_begin);
475e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
476e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        typedef std::set<uint32_t>::iterator It;
477ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes        It it = offsets_.upper_bound(last_offset);
478e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        CHECK(it != offsets_.end());
479e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes        end_native_pc = reinterpret_cast<const uint8_t*>(oat_begin) + *it;
480e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes      }
481ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes      CHECK(native_pc < end_native_pc);
4823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      disassembler_->Dump(os, native_pc, end_native_pc);
483e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes    }
484e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  }
485e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes
48681f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  const std::string host_prefix_;
4873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const OatFile& oat_file_;
4883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  std::vector<const OatFile::OatDexFile*> oat_dex_files_;
489e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes  std::set<uint32_t> offsets_;
4903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  UniquePtr<Disassembler> disassembler_;
491aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom};
492aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
4933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogersclass ImageDumper {
49427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom public:
4953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  explicit ImageDumper(std::ostream& os, const std::string& image_filename,
4963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                       const std::string& host_prefix, Space& image_space,
4973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                       const ImageHeader& image_header) : os_(os),
4983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                       image_filename_(image_filename), host_prefix_(host_prefix),
4993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                       image_space_(image_space), image_header_(image_header) {
5003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
50127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
5023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  void Dump() {
5033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "MAGIC:\n";
5043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << image_header_.GetMagic() << "\n\n";
505e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
5063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "IMAGE BEGIN:\n";
5073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n";
508aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
5093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "OAT CHECKSUM:\n";
5103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << StringPrintf("0x%08x\n\n", image_header_.GetOatChecksum());
511916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
5123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "OAT BEGIN:\n";
5133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << reinterpret_cast<void*>(image_header_.GetOatBegin()) << "\n\n";
514aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
5153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "OAT END:\n";
5163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << reinterpret_cast<void*>(image_header_.GetOatEnd()) << "\n\n";
5173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
5183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "ROOTS:\n";
5193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n";
520418d20fc407052d4152157f61e7453359f902383Elliott Hughes    CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax));
52127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
52227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
52334f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      const char* image_root_description = image_roots_descriptions_[i];
5243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      Object* image_root_object = image_header_.GetImageRoot(image_root);
5253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os_ << StringPrintf("%s: %p\n", image_root_description, image_root_object);
52634f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      if (image_root_object->IsObjectArray()) {
52734f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this)
52834f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        ObjectArray<Object>* image_root_object_array
52934f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom            = down_cast<ObjectArray<Object>*>(image_root_object);
53034f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        //  = image_root_object->AsObjectArray<Object>();
53134f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        for (int i = 0; i < image_root_object_array->GetLength(); i++) {
532d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          Object* value = image_root_object_array->Get(i);
533d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          if (value != NULL) {
5343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            os_ << "\t" << i << ": ";
535d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            std::string summary;
536d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            PrettyObjectValue(summary, value->GetClass(), value);
5373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            os_ << summary;
538d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          } else {
5393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            os_ << StringPrintf("\t%d: null\n", i);
540d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
54134f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        }
54234f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      }
54327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    }
5443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "\n";
54527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
5464dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom    os_ << "OAT LOCATION:\n" << std::flush;
547aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
5483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    Object* oat_location_object = image_header_.GetImageRoot(ImageHeader::kOatLocation);
5493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::string oat_location(oat_location_object->AsString()->ToModifiedUtf8());
5504dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom    os_ << oat_location;
5513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (!host_prefix_.empty()) {
5523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      oat_location = host_prefix_ + oat_location;
5533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os_ << " (" << oat_location << ")";
554aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
5554dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom    os_ << "\n";
556ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const OatFile* oat_file = class_linker->FindOatFileFromOatLocation(oat_location);
557aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (oat_file == NULL) {
5584dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom      os_ << "NOT FOUND\n";
559aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return;
560aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
5614dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom    os_ << "\n";
562aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
5633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.oat_file_bytes = oat_file->Size();
56478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
56581f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    oat_dumper_.reset(new OatDumper(host_prefix_, *oat_file));
5663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
5673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "OBJECTS:\n" << std::flush;
568b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes    HeapBitmap* heap_bitmap = Runtime::Current()->GetHeap()->GetLiveBits();
5693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    DCHECK(heap_bitmap != NULL);
5703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    heap_bitmap->Walk(ImageDumper::Callback, this);
5713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "\n";
5723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
5733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "STATS:\n" << std::flush;
5743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    UniquePtr<File> file(OS::OpenFile(image_filename_.c_str(), false));
5753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.file_bytes = file->Length();
5763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t header_bytes = sizeof(ImageHeader);
5773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.header_bytes = header_bytes;
5783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t alignment_bytes = RoundUp(header_bytes, kObjectAlignment) - header_bytes;
5793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.alignment_bytes += alignment_bytes;
5803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    stats_.Dump(os_);
5813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << "\n";
58227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
5833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    os_ << std::flush;
5843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
5853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    oat_dumper_->Dump(os_);
5863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
587d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
5883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers private:
58927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
590d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  static void PrettyObjectValue(std::string& summary, Class* type, Object* value) {
591d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    CHECK(type != NULL);
592d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (value == NULL) {
593d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "null   %s\n", PrettyDescriptor(type).c_str());
594d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsStringClass()) {
595d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      String* string = value->AsString();
596d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   String: \"%s\"\n", string, string->ToModifiedUtf8().c_str());
597d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (value->IsClass()) {
598d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Class* klass = value->AsClass();
599d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   Class: %s\n", klass, PrettyDescriptor(klass).c_str());
600d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (value->IsField()) {
601d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Field* field = value->AsField();
602d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   Field: %s\n", field, PrettyField(field).c_str());
603d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (value->IsMethod()) {
604d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Method* method = value->AsMethod();
605d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   Method: %s\n", method, PrettyMethod(method).c_str());
606d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
607d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   %s\n", value, PrettyDescriptor(type).c_str());
608d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
609d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
610d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
611d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  static void PrintField(std::string& summary, Field* field, Object* obj) {
612d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    FieldHelper fh(field);
613d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    Class* type = fh.GetType();
614d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    StringAppendF(&summary, "\t%s: ", fh.GetName());
615d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (type->IsPrimitiveLong()) {
616d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%lld (0x%llx)\n", field->Get64(obj), field->Get64(obj));
617d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsPrimitiveDouble()) {
618d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj));
619d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsPrimitiveFloat()) {
620d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%f (%a)\n", field->GetFloat(obj), field->GetFloat(obj));
621d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsPrimitive()){
622d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%d (0x%x)\n", field->Get32(obj), field->Get32(obj));
623d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
624d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Object* value = field->GetObj(obj);
625d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      PrettyObjectValue(summary, type, value);
626d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
627d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
628d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
629d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  static void DumpFields(std::string& summary, Object* obj, Class* klass) {
630d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    Class* super = klass->GetSuperClass();
631d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (super != NULL) {
632d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      DumpFields(summary, obj, super);
633d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
634d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    ObjectArray<Field>* fields = klass->GetIFields();
635d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (fields != NULL) {
636d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < fields->GetLength(); i++) {
637d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        Field* field = fields->Get(i);
638d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        PrintField(summary, field, obj);
639d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
640d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
641d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
642d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
6433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  bool InDumpSpace(const Object* object) {
6443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return image_space_.Contains(object);
645f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
6463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
647f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  const void* GetOatCodeBegin(Method* m) {
6483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    Runtime* runtime = Runtime::Current();
6493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    const void* code = m->GetCode();
650fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers    if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
6513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      code = oat_dumper_->GetOatCode(m);
6523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
653f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    if (oat_dumper_->GetInstructionSet() == kThumb2) {
654f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom      code = reinterpret_cast<void*>(reinterpret_cast<uint32_t>(code) & ~0x1);
655f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
6563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return code;
6573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  }
6583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
659f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  uint32_t GetOatCodeSize(Method* m) {
660f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetOatCodeBegin(m));
661f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    if (oat_code_begin == NULL) {
662f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom      return 0;
663f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
664f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    return oat_code_begin[-1];
665f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
666f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
667f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  const void* GetOatCodeEnd(Method* m) {
668f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetOatCodeBegin(m));
669f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    if (oat_code_begin == NULL) {
670f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom      return NULL;
671f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    }
672f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom    return oat_code_begin + GetOatCodeSize(m);
673f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom  }
674f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom
67578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  static void Callback(Object* obj, void* arg) {
67678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(obj != NULL);
67778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(arg != NULL);
6783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    ImageDumper* state = reinterpret_cast<ImageDumper*>(arg);
67978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    if (!state->InDumpSpace(obj)) {
68078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      return;
68178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
682916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
683916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes = obj->SizeOf();
684916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
685916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.object_bytes += object_bytes;
686916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.alignment_bytes += alignment_bytes;
687916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
68878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    std::string summary;
689d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    Class* obj_class = obj->GetClass();
690d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj_class->IsArrayClass()) {
691d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: %s length:%d\n", obj, PrettyDescriptor(obj_class).c_str(),
692d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    obj->AsArray()->GetLength());
693d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
69478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      Class* klass = obj->AsClass();
695d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.Class \"%s\" (", obj,
696d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    PrettyDescriptor(klass).c_str());
6973b6baaa203fa63f1522b2172a1645f90412afdaeElliott Hughes      std::ostringstream ss;
698d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      ss << klass->GetStatus() << ")\n";
699e10b6974d54f38001aee7bec518d45a7d4fb64c1Brian Carlstrom      summary += ss.str();
70078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else if (obj->IsField()) {
701d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.reflect.Field %s\n", obj,
702d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    PrettyField(obj->AsField()).c_str());
703d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsMethod()) {
704d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.reflect.Method %s\n", obj,
705d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    PrettyMethod(obj->AsMethod()).c_str());
706d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj_class->IsStringClass()) {
707d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.String \"%s\"\n", obj,
708d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    obj->AsString()->ToModifiedUtf8().c_str());
70978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
710d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: %s\n", obj, PrettyDescriptor(obj_class).c_str());
71178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
712d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    DumpFields(summary, obj, obj_class);
713d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj->IsObjectArray()) {
714d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      ObjectArray<Object>* obj_array = obj->AsObjectArray<Object>();
715d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      int32_t length = obj_array->GetLength();
716d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < length; i++) {
717d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        Object* value = obj_array->Get(i);
718d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        size_t run = 0;
719d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t j = i + 1; j < length; j++) {
720d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          if (value == obj_array->Get(j)) {
721d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            run++;
722d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          } else {
723d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            break;
724d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
725d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
726d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        if (run == 0) {
727d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          StringAppendF(&summary, "\t%d: ", i);
72878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        } else {
729c1051ae94c5bd45367152a603f3946a933ad91faElliott Hughes          StringAppendF(&summary, "\t%d to %zd: ", i, i + run);
730d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          i = i + run;
73178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        }
732d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        Class* value_class = value == NULL ? obj_class->GetComponentType() : value->GetClass();
733d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        PrettyObjectValue(summary, value_class, value);
734d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
735d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
736d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      ObjectArray<Field>* sfields = obj->AsClass()->GetSFields();
737d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      if (sfields != NULL) {
738d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        summary += "\t\tSTATICS:\n";
739d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t i = 0; i < sfields->GetLength(); i++) {
740d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          Field* field = sfields->Get(i);
741d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          PrintField(summary, field, NULL);
742d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
743d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
744d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsMethod()) {
745d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Method* method = obj->AsMethod();
746d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      if (method->IsNative()) {
747d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        DCHECK(method->GetGcMap() == NULL) << PrettyMethod(method);
748e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_EQ(0U, method->GetGcMapLength()) << PrettyMethod(method);
7493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
7503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first_occurrence;
7513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t invoke_stub_size = state->ComputeOatSize(
7523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurrence);
7533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurrence) {
7543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.managed_to_native_code_bytes += invoke_stub_size;
7553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
756f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        const void* oat_code = state->GetOatCodeBegin(method);
7573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t code_size = state->ComputeOatSize(oat_code, &first_occurrence);
7583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurrence) {
7593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.native_to_managed_code_bytes += code_size;
7603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
7613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (oat_code != method->GetCode()) {
7623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          StringAppendF(&summary, "\t\tOAT CODE: %p\n", oat_code);
7633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
7641984651929744dd603fd082e23eacd877b9bc177Ian Rogers      } else if (method->IsAbstract() || method->IsCalleeSaveMethod() ||
7651984651929744dd603fd082e23eacd877b9bc177Ian Rogers          method->IsResolutionMethod()) {
766d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        DCHECK(method->GetGcMap() == NULL) << PrettyMethod(method);
767e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_EQ(0U, method->GetGcMapLength()) << PrettyMethod(method);
7683320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
769916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      } else {
770e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK(method->GetGcMap() != NULL) << PrettyMethod(method);
771e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_NE(0U, method->GetGcMapLength()) << PrettyMethod(method);
772916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
7736d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers        const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem();
774d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
775916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        state->stats_.dex_instruction_bytes += dex_instruction_bytes;
776e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
7773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first_occurance;
7783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t gc_map_bytes = state->ComputeOatSize(method->GetGcMapRaw(), &first_occurance);
7793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurance) {
7803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.gc_map_bytes += gc_map_bytes;
7813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
7823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
7833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t pc_mapping_table_bytes =
7843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            state->ComputeOatSize(method->GetMappingTableRaw(), &first_occurance);
7853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurance) {
7863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
7873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
7883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
7893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t vmap_table_bytes =
7903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            state->ComputeOatSize(method->GetVmapTableRaw(), &first_occurance);
7913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurance) {
7923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.vmap_table_bytes += vmap_table_bytes;
7933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
7943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
7953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t invoke_stub_size = state->ComputeOatSize(
7963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurance);
7973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurance) {
7983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.native_to_managed_code_bytes += invoke_stub_size;
7993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
800f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        const void* oat_code_begin = state->GetOatCodeBegin(method);
801f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        const void* oat_code_end = state->GetOatCodeEnd(method);
802f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        // TODO: use oat_code_size and remove code_size based on offsets
803f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        // uint32_t oat_code_size = state->GetOatCodeSize(method);
804f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        size_t code_size = state->ComputeOatSize(oat_code_begin, &first_occurance);
8053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        if (first_occurance) {
8063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          state->stats_.managed_code_bytes += code_size;
8073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
8083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        state->stats_.managed_code_bytes_ignoring_deduplication += code_size;
8093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
810f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom        StringAppendF(&summary, "\t\tOAT CODE: %p-%p\n", oat_code_begin, oat_code_end);
811d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        StringAppendF(&summary, "\t\tSIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n",
8123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                      dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes);
8133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
8143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t total_size = dex_instruction_bytes + gc_map_bytes + pc_mapping_table_bytes +
8153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            vmap_table_bytes + invoke_stub_size + code_size + object_bytes;
8163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
8173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double expansion =
8183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            static_cast<double>(code_size) / static_cast<double>(dex_instruction_bytes);
8193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        state->stats_.ComputeOutliers(total_size, expansion, method);
82078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      }
82178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
822d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    std::string descriptor(ClassHelper(obj_class).GetDescriptor());
823d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    state->stats_.descriptor_to_bytes[descriptor] += object_bytes;
824d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    state->stats_.descriptor_to_count[descriptor] += 1;
825d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
82627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    state->os_ << summary << std::flush;
82778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
82827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
8293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  std::set<const void*> already_seen_;
8303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  // Compute the size of the given data within the oat file and whether this is the first time
8313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  // this data has been requested
8323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  size_t ComputeOatSize(const void* oat_data, bool* first_occurance) {
8333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    if (already_seen_.count(oat_data) == 0) {
8343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      *first_occurance = true;
8353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      already_seen_.insert(oat_data);
8363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    } else {
8373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      *first_occurance = false;
8383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
8393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    return oat_dumper_->ComputeSize(oat_data);
84027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  }
841916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
842916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom public:
843916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  struct Stats {
8443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t oat_file_bytes;
845916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t file_bytes;
846916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
847916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t header_bytes;
848916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes;
849916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes;
850916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
851916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_code_bytes;
8523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t managed_code_bytes_ignoring_deduplication;
853916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_to_native_code_bytes;
854916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t native_to_managed_code_bytes;
855916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
8563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t gc_map_bytes;
857916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t pc_mapping_table_bytes;
8583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    size_t vmap_table_bytes;
859916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
860916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t dex_instruction_bytes;
861916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
8623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::vector<Method*> method_outlier;
8633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::vector<size_t> method_outlier_size;
8643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    std::vector<double> method_outlier_expansion;
8653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
8663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    explicit Stats()
8673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        : oat_file_bytes(0),
8683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          file_bytes(0),
869916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          header_bytes(0),
870916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          object_bytes(0),
871916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          alignment_bytes(0),
872916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_code_bytes(0),
8733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          managed_code_bytes_ignoring_deduplication(0),
874916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_to_native_code_bytes(0),
875916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          native_to_managed_code_bytes(0),
8763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          gc_map_bytes(0),
877916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          pc_mapping_table_bytes(0),
8783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          vmap_table_bytes(0),
879916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          dex_instruction_bytes(0) {}
880916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
881e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes    typedef std::map<std::string, size_t> TableBytes;
882916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    TableBytes descriptor_to_bytes;
883916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
884e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes    typedef std::map<std::string, size_t> TableCount;
885916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    TableCount descriptor_to_count;
886916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
8873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    double PercentOfOatBytes(size_t size) {
8883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100;
8893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
8903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
891916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfFileBytes(size_t size) {
892916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
893916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
894916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
895916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfObjectBytes(size_t size) {
896916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
897916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
898916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
8993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    void ComputeOutliers(size_t total_size, double expansion, Method* method) {
9003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier_size.push_back(total_size);
9013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier_expansion.push_back(expansion);
9023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      method_outlier.push_back(method);
9033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
9043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
9053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    void DumpOutliers(std::ostream& os) {
9063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_sizes = 0;
9073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_sizes_squared = 0;
9083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_expansion = 0;
9093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t sum_of_expansion_squared = 0;
9103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t n = method_outlier_size.size();
9113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 0; i < n; i++) {
9123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t cur_size = method_outlier_size[i];
9133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_sizes += cur_size;
9143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_sizes_squared += cur_size * cur_size;
9153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double cur_expansion = method_outlier_expansion[i];
9163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_expansion += cur_expansion;
9173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        sum_of_expansion_squared += cur_expansion * cur_expansion;
9183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
9193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t size_mean = sum_of_sizes / n;
9203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t size_variance = (sum_of_sizes_squared - sum_of_sizes * size_mean) / (n - 1);
9213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      double expansion_mean = sum_of_expansion / n;
9223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      double expansion_variance =
9233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          (sum_of_expansion_squared - sum_of_expansion * expansion_mean) / (n - 1);
9243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
9253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      // Dump methods whose size is a certain number of standard deviations from the mean
9263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t dumped_values = 0;
9273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      size_t skipped_values = 0;
9283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 100; i > 0; i--) {  // i is the current number of standard deviations
9293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        size_t cur_size_variance = i * i * size_variance;
9303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first = true;
9313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        for (size_t j = 0; j < n; j++) {
9323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          size_t cur_size = method_outlier_size[j];
9333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (cur_size > size_mean) {
9343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            size_t cur_var = cur_size - size_mean;
9353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            cur_var = cur_var * cur_var;
9363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            if (cur_var > cur_size_variance) {
9373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              if (dumped_values > 20) {
9383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (i == 1) {
9393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  skipped_values++;
9403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                } else {
9413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  i = 2;  // jump to counting for 1 standard deviation
9423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  break;
9433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
9443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              } else {
9453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (first) {
9463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  os << "\nBig methods (size > " << i << " standard deviations the norm):"
9473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                     << std::endl;
9483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  first = false;
9493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
9503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                os << "\t" << PrettyMethod(method_outlier[j]) << " requires storage of "
9513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                    << PrettySize(cur_size) << std::endl;
9523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                method_outlier_size[j] = 0;  // don't consider this method again
9533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                dumped_values++;
9543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              }
9553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            }
9563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
9573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
9583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
9593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (skipped_values > 0) {
9603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << "\t... skipped " << skipped_values
9613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers           << " methods with size > 1 standard deviation from the norm" << std::endl;
9623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
9633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << std::endl << std::flush;
9643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
9653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      // Dump methods whose expansion is a certain number of standard deviations from the mean
9663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      dumped_values = 0;
9673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      skipped_values = 0;
9683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      for (size_t i = 10; i > 0; i--) {  // i is the current number of standard deviations
9693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        double cur_expansion_variance = i * i * expansion_variance;
9703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        bool first = true;
9713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        for (size_t j = 0; j < n; j++) {
9723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          double cur_expansion = method_outlier_expansion[j];
9733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          if (cur_expansion > expansion_mean) {
9743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            size_t cur_var = cur_expansion - expansion_mean;
9753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            cur_var = cur_var * cur_var;
9763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            if (cur_var > cur_expansion_variance) {
9773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              if (dumped_values > 20) {
9783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (i == 1) {
9793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  skipped_values++;
9803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                } else {
9813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  i = 2;  // jump to counting for 1 standard deviation
9823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  break;
9833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
9843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              } else {
9853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                if (first) {
9863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  os << "\nLarge expansion methods (size > " << i
9873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                      << " standard deviations the norm):" << std::endl;
9883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                  first = false;
9893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                }
9903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                os << "\t" << PrettyMethod(method_outlier[j]) << " expanded code by "
9913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                    << cur_expansion << std::endl;
9923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                method_outlier_expansion[j] = 0.0;  // don't consider this method again
9933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                dumped_values++;
9943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers              }
9953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            }
9963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          }
9973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        }
9983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
9993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      if (skipped_values > 0) {
10003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers        os << "\t... skipped " << skipped_values
10013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers           << " methods with expansion > 1 standard deviation from the norm" << std::endl;
10023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      }
10033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << std::endl << std::flush;
10043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    }
10053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1006916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    void Dump(std::ostream& os) {
10073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << "\tart_file_bytes = " << PrettySize(file_bytes) << std::endl << std::endl
10083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers         << "\tart_file_bytes = header_bytes + object_bytes + alignment_bytes" << std::endl
10093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers         << StringPrintf("\theader_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
10103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         "\tobject_bytes    =  %8zd (%2.0f%% of art file bytes)\n"
10113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         "\talignment_bytes =  %8zd (%2.0f%% of art file bytes)\n",
10123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         header_bytes, PercentOfFileBytes(header_bytes),
10133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         object_bytes, PercentOfFileBytes(object_bytes),
10143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         alignment_bytes, PercentOfFileBytes(alignment_bytes))
10153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers         << std::endl << std::flush;
10163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
1017916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(file_bytes, header_bytes + object_bytes + alignment_bytes);
1018916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1019916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\tobject_bytes = sum of descriptor_to_bytes values below:\n";
1020916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      size_t object_bytes_total = 0;
1021916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      typedef TableBytes::const_iterator It;  // TODO: C++0x auto
1022916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      for (It it = descriptor_to_bytes.begin(), end = descriptor_to_bytes.end(); it != end; ++it) {
1023955724179c6c739524f610023287f56b24dc31deElliott Hughes        const std::string& descriptor(it->first);
1024916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        size_t bytes = it->second;
1025916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        size_t count = descriptor_to_count[descriptor];
1026916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        double average = static_cast<double>(bytes) / static_cast<double>(count);
1027916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        double percent = PercentOfObjectBytes(bytes);
1028ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes        os << StringPrintf("\t%32s %8zd bytes %6zd instances "
1029916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           "(%3.0f bytes/instance) %2.0f%% of object_bytes\n",
1030916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           descriptor.c_str(), bytes, count,
1031916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           average, percent);
1032916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1033916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        object_bytes_total += bytes;
1034916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      }
10353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << std::endl << std::flush;
1036916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(object_bytes, object_bytes_total);
1037916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
10383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << StringPrintf("\tmanaged_code_bytes           = %8zd (%2.0f%% of oat file bytes)\n"
10393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         "\tmanaged_to_native_code_bytes = %8zd (%2.0f%% of oat file bytes)\n"
10403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         "\tnative_to_managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n",
10413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         managed_code_bytes, PercentOfOatBytes(managed_code_bytes),
10423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         managed_to_native_code_bytes, PercentOfOatBytes(managed_to_native_code_bytes),
10433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         native_to_managed_code_bytes, PercentOfOatBytes(native_to_managed_code_bytes))
10443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers         << std::endl << std::flush;
10453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
10463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << StringPrintf("\tgc_map_bytes           = %7zd (%2.0f%% of oat file_bytes)\n"
10473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         "\tpc_mapping_table_bytes = %7zd (%2.0f%% of oat file_bytes)\n"
10483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         "\tvmap_table_bytes       = %7zd (%2.0f%% of oat file_bytes)\n",
10493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         gc_map_bytes, PercentOfOatBytes(gc_map_bytes),
10503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         pc_mapping_table_bytes, PercentOfOatBytes(pc_mapping_table_bytes),
10513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers                         vmap_table_bytes, PercentOfOatBytes(vmap_table_bytes))
10523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers         << std::endl << std::flush;
1053916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1054ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tdex_instruction_bytes = %zd\n", dex_instruction_bytes);
10553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << StringPrintf("\tmanaged_code_bytes expansion = %.2f (ignoring deduplication %.2f)\n",
10563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          static_cast<double>(managed_code_bytes) / static_cast<double>(dex_instruction_bytes),
10573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers          static_cast<double>(managed_code_bytes_ignoring_deduplication) /
10583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers            static_cast<double>(dex_instruction_bytes));
10593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      os << std::endl << std::flush;
10603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers
10613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers      DumpOutliers(os);
1062916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
1063916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  } stats_;
1064916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
1065916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom private:
10663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  UniquePtr<OatDumper> oat_dumper_;
106727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream& os_;
10683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const std::string image_filename_;
10693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const std::string host_prefix_;
10703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  Space& image_space_;
10713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  const ImageHeader& image_header_;
1072d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
10733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  DISALLOW_COPY_AND_ASSIGN(ImageDumper);
107478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
107578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
107678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint oatdump(int argc, char** argv) {
107778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  // Skip over argv[0].
107878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argv++;
107978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argc--;
108078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
108178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (argc == 0) {
1082aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "No arguments specified\n");
108378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    usage();
108478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
108578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1086aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  const char* oat_filename = NULL;
108778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const char* image_filename = NULL;
108878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const char* boot_image_filename = NULL;
108958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  std::string host_prefix;
109027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream* os = &std::cout;
109127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  UniquePtr<std::ofstream> out;
109278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
109378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  for (int i = 0; i < argc; i++) {
109478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    const StringPiece option(argv[i]);
1095a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    if (option.starts_with("--oat-file=")) {
1096a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      oat_filename = option.substr(strlen("--oat-file=")).data();
1097aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    } else if (option.starts_with("--image=")) {
109878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      image_filename = option.substr(strlen("--image=")).data();
1099e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    } else if (option.starts_with("--boot-image=")) {
1100e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      boot_image_filename = option.substr(strlen("--boot-image=")).data();
110158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    } else if (option.starts_with("--host-prefix=")) {
110258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      host_prefix = option.substr(strlen("--host-prefix=")).data();
110327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    } else if (option.starts_with("--output=")) {
110427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      const char* filename = option.substr(strlen("--output=")).data();
110527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      out.reset(new std::ofstream(filename));
110627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      if (!out->good()) {
1107aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom        fprintf(stderr, "Failed to open output filename %s\n", filename);
110827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        usage();
110927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      }
111027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      os = out.get();
111178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
1112aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Unknown argument %s\n", option.data());
111378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      usage();
111478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
111578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
111678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1117aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename == NULL && oat_filename == NULL) {
1118362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified\n");
1119362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
112078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
112178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1122aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename != NULL && oat_filename != NULL) {
1123362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified but not both\n");
1124362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
1125aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
1126aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
112781f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  if (host_prefix.empty()) {
112881f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    const char* android_product_out = getenv("ANDROID_PRODUCT_OUT");
112981f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    if (android_product_out != NULL) {
113081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom        host_prefix = android_product_out;
113181f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    }
113281f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom  }
113381f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom
1134aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (oat_filename != NULL) {
11353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, NULL);
1136aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (oat_file == NULL) {
1137aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Failed to open oat file from %s\n", oat_filename);
1138aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return EXIT_FAILURE;
1139aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
114081f3ca17e9e8d360cc4a1b6c3155cf01ba3be3bcBrian Carlstrom    OatDumper oat_dumper(host_prefix, *oat_file);
11413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers    oat_dumper.Dump(*os);
1142aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return EXIT_SUCCESS;
1143aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
1144aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
114578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  Runtime::Options options;
114678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string image_option;
1147e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string oat_option;
114878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string boot_image_option;
1149e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string boot_oat_option;
115058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (boot_image_filename != NULL) {
115158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += "-Ximage:";
115258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += boot_image_filename;
115358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
115458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
1155aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename != NULL) {
1156aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += "-Ximage:";
1157aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += image_filename;
1158aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
1159aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
116058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
116158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (!host_prefix.empty()) {
116258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
116378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
116478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
116578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  UniquePtr<Runtime> runtime(Runtime::Create(options, false));
116678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (runtime.get() == NULL) {
1167aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Failed to create runtime\n");
116878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
116978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
117078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
1171b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes  Heap* heap = Runtime::Current()->GetHeap();
1172fddf6f6b4af42c32dd2e92234bab0741118d092eBrian Carlstrom  ImageSpace* image_space = heap->GetImageSpace();
117378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  CHECK(image_space != NULL);
117478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const ImageHeader& image_header = image_space->GetImageHeader();
117578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (!image_header.IsValid()) {
1176aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Invalid image header %s\n", image_filename);
117778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
117878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
11793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  ImageDumper image_dumper(*os, image_filename, host_prefix, *image_space, image_header);
11803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers  image_dumper.Dump();
118178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return EXIT_SUCCESS;
118278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
118378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
118478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom} // namespace art
118578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
118678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint main(int argc, char** argv) {
118778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return art::oatdump(argc, argv);
118878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
1189