oatdump.cc revision 2faa5f1271587cda765f26bcf2951065300a01ff
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"
27916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom#include "file.h"
2878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "image.h"
296d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h"
30e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes#include "os.h"
3178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "runtime.h"
3278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "space.h"
3378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "stringpiece.h"
3478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
3578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromnamespace art {
3678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
3778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromstatic void usage() {
3878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
3978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "Usage: oatdump [options] ...\n"
4029e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "    Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art --host-prefix=$ANDROID_PRODUCT_OUT\n"
4129e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "    Example: adb shell oatdump --image=/system/framework/boot.art\n"
4278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "\n");
4378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
44a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom          "  --oat-file=<file.oat>: specifies an input oat filename.\n"
4529e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --image=/system/framework/boot.oat\n"
46aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom          "\n");
47aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  fprintf(stderr,
48aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom          "  --image=<file.art>: specifies an input image filename.\n"
4929e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --image=/system/framework/boot.art\n"
50e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
5178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  fprintf(stderr,
52e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "  --boot-image=<file.art>: provide the image file for the boot class path.\n"
5329e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom          "      Example: --boot-image=/system/framework/boot.art\n"
54e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom          "\n");
55e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  fprintf(stderr,
5658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "  --host-prefix may be used to translate host paths to target paths during\n"
5758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "      cross compilation.\n"
5858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom          "      Example: --host-prefix=out/target/product/crespo\n"
5978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          "\n");
6027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  fprintf(stderr,
6127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "  --output=<file> may be used to send the output to a file.\n"
6227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "      Example: --output=/tmp/oatdump.txt\n"
6327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom          "\n");
6478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  exit(EXIT_FAILURE);
6578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
6678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
67ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogersconst char* image_roots_descriptions_[] = {
6878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  "kJniStubArray",
69e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kAbstractMethodErrorStubArray",
70ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  "kInstanceResolutionStubArray",
71ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers  "kStaticResolutionStubArray",
721cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers  "kUnknownMethodResolutionStubArray",
73e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kCalleeSaveMethod",
74aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  "kRefsOnlySaveMethod",
75aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  "kRefsAndArgsSaveMethod",
76e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  "kOatLocation",
7758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  "kDexCaches",
7834f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom  "kClassRoots",
7978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
8078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
8127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstromclass OatDump {
82aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom public:
83aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  static void Dump(const std::string& oat_filename,
84aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                   const std::string& host_prefix,
85aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                   std::ostream& os,
86aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                   const OatFile& oat_file) {
87aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    const OatHeader& oat_header = oat_file.GetOatHeader();
88aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
89aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "MAGIC:\n";
90aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetMagic() << "\n\n";
91aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
92aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "CHECKSUM:\n";
93aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("%08x\n\n", oat_header.GetChecksum());
94aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
95aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "DEX FILE COUNT:\n";
96aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetDexFileCount() << "\n\n";
97aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
98aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "EXECUTABLE OFFSET:\n";
99aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("%08x\n\n", oat_header.GetExecutableOffset());
100aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
10130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "BEGIN:\n";
10230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<const void*>(oat_file.Begin()) << "\n\n";
103aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
10430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "END:\n";
10530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<const void*>(oat_file.End()) << "\n\n";
106aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
107aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
108aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
109ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file.GetOatDexFiles();
110aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    for (size_t i = 0; i < oat_dex_files.size(); i++) {
111aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
112aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CHECK(oat_dex_file != NULL);
113aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      DumpOatDexFile(host_prefix, os, oat_file, *oat_dex_file);
114aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
115aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
116aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
117aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom private:
118aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  static void DumpOatDexFile(const std::string& host_prefix,
119aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                             std::ostream& os,
120aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                             const OatFile& oat_file,
121aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                             const OatFile::OatDexFile& oat_dex_file) {
122aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "OAT DEX FILE:\n";
123955724179c6c739524f610023287f56b24dc31deElliott Hughes    std::string dex_file_location(oat_dex_file.GetDexFileLocation());
124aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "location: " << dex_file_location;
125aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (!host_prefix.empty()) {
126aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      dex_file_location = host_prefix + dex_file_location;
127b7bbba49d88eae58223d9878da4069bf6d7140bfBrian Carlstrom      os << " (" << dex_file_location << ")";
128aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
129b7bbba49d88eae58223d9878da4069bf6d7140bfBrian Carlstrom    os << "\n";
130aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("checksum: %08x\n", oat_dex_file.GetDexFileChecksum());
131aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    const DexFile* dex_file = DexFile::Open(dex_file_location, "");
132aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (dex_file == NULL) {
133aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      os << "NOT FOUND\n\n";
134aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return;
135aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
136aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) {
137aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
138aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const char* descriptor = dex_file->GetClassDescriptor(class_def);
139aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file.GetOatClass(class_def_index));
140aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CHECK(oat_class.get() != NULL);
141ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("%zd: %s (type_idx=%d) (", class_def_index, descriptor, class_def.class_idx_)
142e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom         << oat_class->GetStatus() << ")\n";
143aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      DumpOatClass(os, oat_file, *oat_class.get(), *dex_file, class_def);
144aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
145aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
146aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
147aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
148aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
149aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  static void DumpOatClass(std::ostream& os,
150aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                           const OatFile& oat_file,
151aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                           const OatFile::OatClass& oat_class,
152aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                           const DexFile& dex_file,
153aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                           const DexFile::ClassDef& class_def) {
154aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    const byte* class_data = dex_file.GetClassData(class_def);
1550571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    if (class_data == NULL) {  // empty class such as a marker interface?
1560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      return;
1570571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    }
1580571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    ClassDataItemIterator it(dex_file, class_data);
159aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
160aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    // just skipping through the fields to advance class_data
1610571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextStaticField()) {
1620571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
163aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
1640571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextInstanceField()) {
1650571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
166aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
167aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
1680571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    uint32_t method_index = 0;
1690571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextDirectMethod()) {
1700571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
1710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, it.GetMemberIndex());
1720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      method_index++;
1730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
174aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
1750571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextVirtualMethod()) {
1760571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
1770571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, it.GetMemberIndex());
1780571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      method_index++;
1790571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
180aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
1810571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    DCHECK(!it.HasNext());
182aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
183aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
184aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  static void DumpOatMethod(std::ostream& os,
185aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                            uint32_t method_index,
186aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                            const OatFile& oat_file,
187aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                            const OatFile::OatMethod& oat_method,
188aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                            const DexFile& dex_file,
1890571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers                            uint32_t method_idx) {
1900571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
191aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    const char* name = dex_file.GetMethodName(method_id);
192955724179c6c739524f610023287f56b24dc31deElliott Hughes    std::string signature(dex_file.GetMethodSignature(method_id));
193aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t%d: %s %s (method_idx=%d)\n",
1940571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers                       method_index, name, signature.c_str(), method_idx);
195aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tcode: %p (offset=%08x)\n",
196ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetCode(), oat_method.GetCodeOffset());
197ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes    os << StringPrintf("\t\tframe_size_in_bytes: %zd\n",
198ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetFrameSizeInBytes());
199aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tcore_spill_mask: %08x\n",
200ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetCoreSpillMask());
201aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tfp_spill_mask: %08x\n",
202ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetFpSpillMask());
203aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tmapping_table: %p (offset=%08x)\n",
204ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetMappingTable(), oat_method.GetMappingTableOffset());
205aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tvmap_table: %p (offset=%08x)\n",
206ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetVmapTable(), oat_method.GetVmapTableOffset());
207e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    os << StringPrintf("\t\tgc_map: %p (offset=%08x)\n",
208e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                       oat_method.GetGcMap(), oat_method.GetGcMapOffset());
209aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tinvoke_stub: %p (offset=%08x)\n",
210ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetInvokeStub(), oat_method.GetInvokeStubOffset());
211aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
212aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom};
213aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
214aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstromclass ImageDump {
21527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom public:
216916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  static void Dump(const std::string& image_filename,
217aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                   const std::string& host_prefix,
218916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                   std::ostream& os,
219916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                   Space& image_space,
220916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                   const ImageHeader& image_header) {
22127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    os << "MAGIC:\n";
22227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    os << image_header.GetMagic() << "\n\n";
22327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
22430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "IMAGE BEGIN:\n";
22530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<void*>(image_header.GetImageBegin()) << "\n\n";
226e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
227aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "OAT CHECKSUM:\n";
228aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("%08x\n\n", image_header.GetOatChecksum());
229aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
23030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "OAT BEGIN:\n";
23130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<void*>(image_header.GetOatBegin()) << "\n\n";
232916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
23330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "OAT END:\n";
23430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<void*>(image_header.GetOatEnd()) << "\n\n";
235aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
23627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    os << "ROOTS:\n";
237aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << reinterpret_cast<void*>(image_header.GetImageRoots()) << "\n";
238418d20fc407052d4152157f61e7453359f902383Elliott Hughes    CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax));
23927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
24027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
24134f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      const char* image_root_description = image_roots_descriptions_[i];
24234f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      Object* image_root_object = image_header.GetImageRoot(image_root);
24334f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      os << StringPrintf("%s: %p\n", image_root_description, image_root_object);
24434f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      if (image_root_object->IsObjectArray()) {
24534f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this)
24634f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        ObjectArray<Object>* image_root_object_array
24734f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom            = down_cast<ObjectArray<Object>*>(image_root_object);
24834f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        //  = image_root_object->AsObjectArray<Object>();
24934f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        for (int i = 0; i < image_root_object_array->GetLength(); i++) {
25034f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom            os << StringPrintf("\t%d: %p\n", i, image_root_object_array->Get(i));
25134f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        }
25234f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      }
25327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    }
25427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    os << "\n";
25527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
25627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    os << "OBJECTS:\n" << std::flush;
257aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    ImageDump state(image_space, os);
25827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    HeapBitmap* heap_bitmap = Heap::GetLiveBits();
25927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    DCHECK(heap_bitmap != NULL);
260aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    heap_bitmap->Walk(ImageDump::Callback, &state);
261916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    os << "\n";
262916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
263916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    os << "STATS:\n" << std::flush;
264916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    UniquePtr<File> file(OS::OpenFile(image_filename.c_str(), false));
265916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state.stats_.file_bytes = file->Length();
266e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    size_t header_bytes = sizeof(ImageHeader);
267e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    state.stats_.header_bytes = header_bytes;
268e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    size_t alignment_bytes = RoundUp(header_bytes, kObjectAlignment) - header_bytes;
269e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    state.stats_.alignment_bytes += alignment_bytes;
270916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state.stats_.Dump(os);
271aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "\n";
272916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
273916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    os << std::flush;
274aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
275aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "OAT LOCATION:\n" << std::flush;
276aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    Object* oat_location_object = image_header.GetImageRoot(ImageHeader::kOatLocation);
277955724179c6c739524f610023287f56b24dc31deElliott Hughes    std::string oat_location(oat_location_object->AsString()->ToModifiedUtf8());
278aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
279aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_location;
280aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (!host_prefix.empty()) {
281aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      oat_location = host_prefix + oat_location;
282b7bbba49d88eae58223d9878da4069bf6d7140bfBrian Carlstrom      os << " (" << oat_location << ")";
283aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
284b7bbba49d88eae58223d9878da4069bf6d7140bfBrian Carlstrom    os << "\n";
285ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom    const OatFile* oat_file = class_linker->FindOatFileFromOatLocation(oat_location);
286aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (oat_file == NULL) {
287aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      os << "NOT FOUND\n";
288aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      os << std::flush;
289aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return;
290aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
291aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "\n";
292aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
293aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
294866c8627626b7c47fb69b498b341772d7dfa7f60Brian Carlstrom    class_linker->RegisterOatFile(*oat_file);
295aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    OatDump::Dump(oat_location, host_prefix, os, *oat_file);
29678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
29778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
29827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom private:
29927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
300aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  ImageDump(const Space& dump_space, std::ostream& os) : dump_space_(dump_space), os_(os) {}
301d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
302aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  ~ImageDump() {}
30327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
30478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  static void Callback(Object* obj, void* arg) {
30578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(obj != NULL);
30678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(arg != NULL);
307aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    ImageDump* state = reinterpret_cast<ImageDump*>(arg);
30878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    if (!state->InDumpSpace(obj)) {
30978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      return;
31078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
311916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
312916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes = obj->SizeOf();
313916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
314916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.object_bytes += object_bytes;
315916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.alignment_bytes += alignment_bytes;
316916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
31778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    std::string summary;
31878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    StringAppendF(&summary, "%p: ", obj);
31978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    if (obj->IsClass()) {
32078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      Class* klass = obj->AsClass();
3216d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers      summary += "CLASS ";
3226d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers      summary += ClassHelper(klass).GetDescriptor();
3233b6baaa203fa63f1522b2172a1645f90412afdaeElliott Hughes      std::ostringstream ss;
324e10b6974d54f38001aee7bec518d45a7d4fb64c1Brian Carlstrom      ss << " (" << klass->GetStatus() << ")";
325e10b6974d54f38001aee7bec518d45a7d4fb64c1Brian Carlstrom      summary += ss.str();
32678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else if (obj->IsMethod()) {
32778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      Method* method = obj->AsMethod();
32878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      StringAppendF(&summary, "METHOD %s", PrettyMethod(method).c_str());
32978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else if (obj->IsField()) {
33078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      Field* field = obj->AsField();
33178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      StringAppendF(&summary, "FIELD %s", PrettyField(field).c_str());
33278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else if (obj->IsArrayInstance()) {
33378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      StringAppendF(&summary, "ARRAY %d", obj->AsArray()->GetLength());
334dbb4079eb1e7d7738c81a97c8dd2550885c1093aElliott Hughes    } else if (obj->GetClass()->IsStringClass()) {
33578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      StringAppendF(&summary, "STRING %s", obj->AsString()->ToModifiedUtf8().c_str());
33678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
33778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      StringAppendF(&summary, "OBJECT");
33878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
33978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    StringAppendF(&summary, "\n");
3406d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers    std::string descriptor(ClassHelper(obj->GetClass()).GetDescriptor());
341916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    StringAppendF(&summary, "\tclass %p: %s\n", obj->GetClass(), descriptor.c_str());
342916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.descriptor_to_bytes[descriptor] += object_bytes;
343916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.descriptor_to_count[descriptor] += 1;
344916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    // StringAppendF(&summary, "\tsize %d (alignment padding %d)\n",
345916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    //               object_bytes, RoundUp(object_bytes, kObjectAlignment) - object_bytes);
34678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    if (obj->IsMethod()) {
34778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      Method* method = obj->AsMethod();
3483320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom      if (!method->IsCalleeSaveMethod()) {
3493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        const int8_t* code =reinterpret_cast<const int8_t*>(method->GetCode());
3503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        StringAppendF(&summary, "\tCODE     %p\n", code);
3513320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom
3523320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        const Method::InvokeStub* invoke_stub = method->GetInvokeStub();
3533320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        StringAppendF(&summary, "\tJNI STUB %p\n", invoke_stub);
354ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogers      }
35578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      if (method->IsNative()) {
35678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        if (method->IsRegistered()) {
357916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          StringAppendF(&summary, "\tNATIVE REGISTERED %p\n", method->GetNativeMethod());
35878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        } else {
35978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom          StringAppendF(&summary, "\tNATIVE UNREGISTERED\n");
36078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        }
361d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        DCHECK(method->GetGcMap() == NULL) << PrettyMethod(method);
362e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_EQ(0U, method->GetGcMapLength()) << PrettyMethod(method);
3633320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
364916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      } else if (method->IsAbstract()) {
365916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        StringAppendF(&summary, "\tABSTRACT\n");
366d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        DCHECK(method->GetGcMap() == NULL) << PrettyMethod(method);
367e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_EQ(0U, method->GetGcMapLength()) << PrettyMethod(method);
3683320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
3693320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom      } else if (method->IsCalleeSaveMethod()) {
3703320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        StringAppendF(&summary, "\tCALLEE SAVE METHOD\n");
371d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        DCHECK(method->GetGcMap() == NULL) << PrettyMethod(method);
372e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_EQ(0U, method->GetGcMapLength()) << PrettyMethod(method);
3733320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
374916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      } else {
375e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK(method->GetGcMap() != NULL) << PrettyMethod(method);
376e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_NE(0U, method->GetGcMapLength()) << PrettyMethod(method);
377916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
378e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        size_t register_map_bytes = method->GetGcMapLength();
379e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        state->stats_.register_map_bytes += register_map_bytes;
380ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes        StringAppendF(&summary, "GC=%zd ", register_map_bytes);
381e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
382e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        size_t pc_mapping_table_bytes = method->GetMappingTableLength();
383e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
384ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes        StringAppendF(&summary, "Mapping=%zd ", pc_mapping_table_bytes);
385916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
3866d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers        const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem();
387d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
388916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        state->stats_.dex_instruction_bytes += dex_instruction_bytes;
389e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
390ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes        StringAppendF(&summary, "\tSIZE Code=%zd GC=%zd Mapping=%zd",
391e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                      dex_instruction_bytes, register_map_bytes, pc_mapping_table_bytes);
39278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      }
39378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
39427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    state->os_ << summary << std::flush;
39578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
39627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
39727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  bool InDumpSpace(const Object* object) {
39830fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    return dump_space_.Contains(object);
39927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  }
400916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
401916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom public:
402916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  struct Stats {
403916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t file_bytes;
404916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
405916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t header_bytes;
406916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes;
407916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes;
408916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
409916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_code_bytes;
410916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_to_native_code_bytes;
411916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t native_to_managed_code_bytes;
412916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
413916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t register_map_bytes;
414916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t pc_mapping_table_bytes;
415916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
416916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t dex_instruction_bytes;
417916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
418916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    Stats()
419916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        : file_bytes(0),
420916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          header_bytes(0),
421916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          object_bytes(0),
422916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          alignment_bytes(0),
423916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_code_bytes(0),
424916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_to_native_code_bytes(0),
425916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          native_to_managed_code_bytes(0),
426916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          register_map_bytes(0),
427916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          pc_mapping_table_bytes(0),
428916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          dex_instruction_bytes(0) {}
429916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
430e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes    typedef std::map<std::string, size_t> TableBytes;
431916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    TableBytes descriptor_to_bytes;
432916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
433e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes    typedef std::map<std::string, size_t> TableCount;
434916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    TableCount descriptor_to_count;
435916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
436916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfFileBytes(size_t size) {
437916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
438916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
439916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
440916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfObjectBytes(size_t size) {
441916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
442916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
443916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
444916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    void Dump(std::ostream& os) {
445ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tfile_bytes = %zd\n", file_bytes);
446916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
447916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
448916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\tfile_bytes = header_bytes + object_bytes + alignment_bytes\n";
449ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\theader_bytes    = %10zd (%2.0f%% of file_bytes)\n",
450916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         header_bytes, PercentOfFileBytes(header_bytes));
451ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tobject_bytes    = %10zd (%2.0f%% of file_bytes)\n",
452916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         object_bytes, PercentOfFileBytes(object_bytes));
453ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\talignment_bytes = %10zd (%2.0f%% of file_bytes)\n",
454916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         alignment_bytes, PercentOfFileBytes(alignment_bytes));
455916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
456916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
457916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(file_bytes, header_bytes + object_bytes + alignment_bytes);
458916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
459916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\tobject_bytes = sum of descriptor_to_bytes values below:\n";
460916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      size_t object_bytes_total = 0;
461916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      typedef TableBytes::const_iterator It;  // TODO: C++0x auto
462916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      for (It it = descriptor_to_bytes.begin(), end = descriptor_to_bytes.end(); it != end; ++it) {
463955724179c6c739524f610023287f56b24dc31deElliott Hughes        const std::string& descriptor(it->first);
464916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        size_t bytes = it->second;
465916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        size_t count = descriptor_to_count[descriptor];
466916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        double average = static_cast<double>(bytes) / static_cast<double>(count);
467916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        double percent = PercentOfObjectBytes(bytes);
468ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes        os << StringPrintf("\t%32s %8zd bytes %6zd instances "
469916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           "(%3.0f bytes/instance) %2.0f%% of object_bytes\n",
470916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           descriptor.c_str(), bytes, count,
471916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           average, percent);
472916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
473916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        object_bytes_total += bytes;
474916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      }
475916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
476916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
477916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(object_bytes, object_bytes_total);
478916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
479ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tmanaged_code_bytes           = %8zd (%2.0f%% of object_bytes)\n",
480916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         managed_code_bytes, PercentOfObjectBytes(managed_code_bytes));
481ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tmanaged_to_native_code_bytes = %8zd (%2.0f%% of object_bytes)\n",
482916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         managed_to_native_code_bytes,
483916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         PercentOfObjectBytes(managed_to_native_code_bytes));
484ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tnative_to_managed_code_bytes = %8zd (%2.0f%% of object_bytes)\n",
485916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         native_to_managed_code_bytes,
486916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         PercentOfObjectBytes(native_to_managed_code_bytes));
487916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
488916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
489916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
490ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tregister_map_bytes     = %7zd (%2.0f%% of object_bytes)\n",
491916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         register_map_bytes, PercentOfObjectBytes(register_map_bytes));
492ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tpc_mapping_table_bytes = %7zd (%2.0f%% of object_bytes)\n",
493916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         pc_mapping_table_bytes, PercentOfObjectBytes(pc_mapping_table_bytes));
494916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
495916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
496916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
497ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tdex_instruction_bytes = %zd\n", dex_instruction_bytes);
498916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << StringPrintf("\tmanaged_code_bytes expansion = %.2f\n",
499916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         static_cast<double>(managed_code_bytes)
500916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         / static_cast<double>(dex_instruction_bytes));
501916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
502916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
503916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
504916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  } stats_;
505916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
506916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom private:
50727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  const Space& dump_space_;
50827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream& os_;
509d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
510aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  DISALLOW_COPY_AND_ASSIGN(ImageDump);
51178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
51278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
51378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint oatdump(int argc, char** argv) {
51478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  // Skip over argv[0].
51578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argv++;
51678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argc--;
51778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
51878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (argc == 0) {
519aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "No arguments specified\n");
52078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    usage();
52178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
52278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
523aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  const char* oat_filename = NULL;
52478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const char* image_filename = NULL;
52578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const char* boot_image_filename = NULL;
52658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  std::string host_prefix;
52727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream* os = &std::cout;
52827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  UniquePtr<std::ofstream> out;
52978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
53078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  for (int i = 0; i < argc; i++) {
53178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    const StringPiece option(argv[i]);
532a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    if (option.starts_with("--oat-file=")) {
533a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      oat_filename = option.substr(strlen("--oat-file=")).data();
534aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    } else if (option.starts_with("--image=")) {
53578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      image_filename = option.substr(strlen("--image=")).data();
536e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    } else if (option.starts_with("--boot-image=")) {
537e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      boot_image_filename = option.substr(strlen("--boot-image=")).data();
53858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    } else if (option.starts_with("--host-prefix=")) {
53958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      host_prefix = option.substr(strlen("--host-prefix=")).data();
54027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    } else if (option.starts_with("--output=")) {
54127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      const char* filename = option.substr(strlen("--output=")).data();
54227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      out.reset(new std::ofstream(filename));
54327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      if (!out->good()) {
544aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom        fprintf(stderr, "Failed to open output filename %s\n", filename);
54527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        usage();
54627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      }
54727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      os = out.get();
54878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
549aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Unknown argument %s\n", option.data());
55078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      usage();
55178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
55278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
55378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
554aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename == NULL && oat_filename == NULL) {
555362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified\n");
556362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
55778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
55878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
559aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename != NULL && oat_filename != NULL) {
560362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified but not both\n");
561362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
562aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
563aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
564aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (oat_filename != NULL) {
565aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    const OatFile* oat_file = OatFile::Open(oat_filename, "", NULL);
566aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (oat_file == NULL) {
567aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Failed to open oat file from %s\n", oat_filename);
568aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return EXIT_FAILURE;
569aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
570aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    OatDump::Dump(oat_filename, host_prefix, *os, *oat_file);
571aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return EXIT_SUCCESS;
572aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
573aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
57478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  Runtime::Options options;
57578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string image_option;
576e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string oat_option;
57778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string boot_image_option;
578e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string boot_oat_option;
57958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (boot_image_filename != NULL) {
58058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += "-Ximage:";
58158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += boot_image_filename;
58258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
58358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
584aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename != NULL) {
585aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += "-Ximage:";
586aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += image_filename;
587aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
588aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
58958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
59058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (!host_prefix.empty()) {
59158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
59278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
59378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
59478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  UniquePtr<Runtime> runtime(Runtime::Create(options, false));
59578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (runtime.get() == NULL) {
596aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Failed to create runtime\n");
59778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
59878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
59978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
60030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  ImageSpace* image_space = Heap::GetSpaces()[Heap::GetSpaces().size()-2]->AsImageSpace();
60178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  CHECK(image_space != NULL);
60278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const ImageHeader& image_header = image_space->GetImageHeader();
60378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (!image_header.IsValid()) {
604aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Invalid image header %s\n", image_filename);
60578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
60678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
607aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  ImageDump::Dump(image_filename, host_prefix, *os, *image_space, image_header);
60878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return EXIT_SUCCESS;
60978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
61078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
61178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom} // namespace art
61278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
61378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint main(int argc, char** argv) {
61478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return art::oatdump(argc, argv);
61578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
616