oatdump.cc revision d5b32607798a46a905ba2d8d5bf7507cc970aa58
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                   std::ostream& os,
85aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                   const OatFile& oat_file) {
86aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    const OatHeader& oat_header = oat_file.GetOatHeader();
87aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
88aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "MAGIC:\n";
89aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetMagic() << "\n\n";
90aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
91aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "CHECKSUM:\n";
92aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("%08x\n\n", oat_header.GetChecksum());
93aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
94aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "DEX FILE COUNT:\n";
95aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << oat_header.GetDexFileCount() << "\n\n";
96aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
97aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "EXECUTABLE OFFSET:\n";
98aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("%08x\n\n", oat_header.GetExecutableOffset());
99aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
10030fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "BEGIN:\n";
10130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<const void*>(oat_file.Begin()) << "\n\n";
102aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
10330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "END:\n";
10430fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<const void*>(oat_file.End()) << "\n\n";
105aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
106aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
107aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
108ba8eee10607a524f43b55a6f33c13924fb16d435Elliott Hughes    std::vector<const OatFile::OatDexFile*> oat_dex_files = oat_file.GetOatDexFiles();
109aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    for (size_t i = 0; i < oat_dex_files.size(); i++) {
110aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const OatFile::OatDexFile* oat_dex_file = oat_dex_files[i];
111aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CHECK(oat_dex_file != NULL);
112a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      DumpOatDexFile(os, oat_file, *oat_dex_file);
113aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
114aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
115aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
116aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom private:
117a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom  static void DumpOatDexFile(std::ostream& os,
118aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                             const OatFile& oat_file,
119aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                             const OatFile::OatDexFile& oat_dex_file) {
120aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "OAT DEX FILE:\n";
121a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str());
1225b332c89fa3fdd7dc184b22c2587d28af304d019Brian Carlstrom    os << StringPrintf("checksum: %08x\n", oat_dex_file.GetDexFileLocationChecksum());
123a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    UniquePtr<const DexFile> dex_file(oat_dex_file.OpenDexFile());
124a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    if (dex_file.get() == NULL) {
125aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      os << "NOT FOUND\n\n";
126aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return;
127aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
128aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) {
129aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
130aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      const char* descriptor = dex_file->GetClassDescriptor(class_def);
131aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file.GetOatClass(class_def_index));
132aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      CHECK(oat_class.get() != NULL);
133ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("%zd: %s (type_idx=%d) (", class_def_index, descriptor, class_def.class_idx_)
134e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom         << oat_class->GetStatus() << ")\n";
135a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom      DumpOatClass(os, oat_file, *oat_class.get(), *(dex_file.get()), class_def);
136aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
137aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
138aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
139aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
140aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
141aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  static void DumpOatClass(std::ostream& os,
142aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                           const OatFile& oat_file,
143aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                           const OatFile::OatClass& oat_class,
144aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                           const DexFile& dex_file,
145aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                           const DexFile::ClassDef& class_def) {
146aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    const byte* class_data = dex_file.GetClassData(class_def);
1470571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    if (class_data == NULL) {  // empty class such as a marker interface?
1480571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      return;
1490571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    }
1500571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    ClassDataItemIterator it(dex_file, class_data);
151aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
152aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    // just skipping through the fields to advance class_data
1530571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextStaticField()) {
1540571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
155aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
1560571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextInstanceField()) {
1570571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
158aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
159aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
1600571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    uint32_t method_index = 0;
1610571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextDirectMethod()) {
1620571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
1630571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, it.GetMemberIndex());
1640571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      method_index++;
1650571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
166aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
1670571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    while (it.HasNextVirtualMethod()) {
1680571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      const OatFile::OatMethod oat_method = oat_class.GetOatMethod(method_index);
1690571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      DumpOatMethod(os, method_index, oat_file, oat_method, dex_file, it.GetMemberIndex());
1700571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      method_index++;
1710571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers      it.Next();
172aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
1730571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    DCHECK(!it.HasNext());
174aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << std::flush;
175aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
176aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  static void DumpOatMethod(std::ostream& os,
177aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                            uint32_t method_index,
178aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                            const OatFile& oat_file,
179aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                            const OatFile::OatMethod& oat_method,
180aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                            const DexFile& dex_file,
1810571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers                            uint32_t method_idx) {
1820571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers    const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
183aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    const char* name = dex_file.GetMethodName(method_id);
184955724179c6c739524f610023287f56b24dc31deElliott Hughes    std::string signature(dex_file.GetMethodSignature(method_id));
185aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t%d: %s %s (method_idx=%d)\n",
1860571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers                       method_index, name, signature.c_str(), method_idx);
187aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tcode: %p (offset=%08x)\n",
188ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetCode(), oat_method.GetCodeOffset());
189ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes    os << StringPrintf("\t\tframe_size_in_bytes: %zd\n",
190ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetFrameSizeInBytes());
191aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tcore_spill_mask: %08x\n",
192ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetCoreSpillMask());
193aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tfp_spill_mask: %08x\n",
194ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetFpSpillMask());
195aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tmapping_table: %p (offset=%08x)\n",
196ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetMappingTable(), oat_method.GetMappingTableOffset());
197aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tvmap_table: %p (offset=%08x)\n",
198ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetVmapTable(), oat_method.GetVmapTableOffset());
199e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom    os << StringPrintf("\t\tgc_map: %p (offset=%08x)\n",
200e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                       oat_method.GetGcMap(), oat_method.GetGcMapOffset());
201aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("\t\tinvoke_stub: %p (offset=%08x)\n",
202ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom                       oat_method.GetInvokeStub(), oat_method.GetInvokeStubOffset());
203aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
204aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom};
205aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
206aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstromclass ImageDump {
20727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom public:
208916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  static void Dump(const std::string& image_filename,
209aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom                   const std::string& host_prefix,
210916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                   std::ostream& os,
211916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                   Space& image_space,
212916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                   const ImageHeader& image_header) {
21327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    os << "MAGIC:\n";
21427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    os << image_header.GetMagic() << "\n\n";
21527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
21630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "IMAGE BEGIN:\n";
21730fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<void*>(image_header.GetImageBegin()) << "\n\n";
218e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom
219aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << "OAT CHECKSUM:\n";
220aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << StringPrintf("%08x\n\n", image_header.GetOatChecksum());
221aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
22230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "OAT BEGIN:\n";
22330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<void*>(image_header.GetOatBegin()) << "\n\n";
224916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
22530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << "OAT END:\n";
22630fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    os << reinterpret_cast<void*>(image_header.GetOatEnd()) << "\n\n";
227aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
22827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    os << "ROOTS:\n";
229aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    os << reinterpret_cast<void*>(image_header.GetImageRoots()) << "\n";
230418d20fc407052d4152157f61e7453359f902383Elliott Hughes    CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax));
23127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    for (int i = 0; i < ImageHeader::kImageRootsMax; i++) {
23227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i);
23334f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      const char* image_root_description = image_roots_descriptions_[i];
23434f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      Object* image_root_object = image_header.GetImageRoot(image_root);
23534f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      os << StringPrintf("%s: %p\n", image_root_description, image_root_object);
23634f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom      if (image_root_object->IsObjectArray()) {
23734f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this)
23834f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        ObjectArray<Object>* image_root_object_array
23934f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom            = down_cast<ObjectArray<Object>*>(image_root_object);
24034f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        //  = image_root_object->AsObjectArray<Object>();
24134f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom        for (int i = 0; i < image_root_object_array->GetLength(); i++) {
242d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          Object* value = image_root_object_array->Get(i);
243d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          if (value != NULL) {
244d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            os << "\t" << i << ": ";
245d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            std::string summary;
246d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            PrettyObjectValue(summary, value->GetClass(), value);
247d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            os << summary;
248d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          } else {
249d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            os << StringPrintf("\t%d: null\n", i);
250d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
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
294a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    OatDump::Dump(oat_location, os, *oat_file);
29578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
29678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
29727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom private:
29827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
299aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  ImageDump(const Space& dump_space, std::ostream& os) : dump_space_(dump_space), os_(os) {}
300d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
301aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  ~ImageDump() {}
30227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
303d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  static void PrettyObjectValue(std::string& summary, Class* type, Object* value) {
304d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    CHECK(type != NULL);
305d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (value == NULL) {
306d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "null   %s\n", PrettyDescriptor(type).c_str());
307d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsStringClass()) {
308d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      String* string = value->AsString();
309d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   String: \"%s\"\n", string, string->ToModifiedUtf8().c_str());
310d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (value->IsClass()) {
311d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Class* klass = value->AsClass();
312d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   Class: %s\n", klass, PrettyDescriptor(klass).c_str());
313d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (value->IsField()) {
314d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Field* field = value->AsField();
315d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   Field: %s\n", field, PrettyField(field).c_str());
316d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (value->IsMethod()) {
317d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Method* method = value->AsMethod();
318d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   Method: %s\n", method, PrettyMethod(method).c_str());
319d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
320d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p   %s\n", value, PrettyDescriptor(type).c_str());
321d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
322d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
323d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
324d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  static void PrintField(std::string& summary, Field* field, Object* obj) {
325d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    FieldHelper fh(field);
326d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    Class* type = fh.GetType();
327d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    StringAppendF(&summary, "\t%s: ", fh.GetName());
328d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (type->IsPrimitiveLong()) {
329d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%lld (0x%llx)\n", field->Get64(obj), field->Get64(obj));
330d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsPrimitiveDouble()) {
331d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj));
332d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsPrimitiveFloat()) {
333d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%f (%a)\n", field->GetFloat(obj), field->GetFloat(obj));
334d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (type->IsPrimitive()){
335d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%d (0x%x)\n", field->Get32(obj), field->Get32(obj));
336d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else {
337d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Object* value = field->GetObj(obj);
338d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      PrettyObjectValue(summary, type, value);
339d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
340d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
341d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
342d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  static void DumpFields(std::string& summary, Object* obj, Class* klass) {
343d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    Class* super = klass->GetSuperClass();
344d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (super != NULL) {
345d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      DumpFields(summary, obj, super);
346d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
347d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    ObjectArray<Field>* fields = klass->GetIFields();
348d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (fields != NULL) {
349d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < fields->GetLength(); i++) {
350d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        Field* field = fields->Get(i);
351d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        PrintField(summary, field, obj);
352d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
353d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    }
354d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers  }
355d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
35678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  static void Callback(Object* obj, void* arg) {
35778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(obj != NULL);
35878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    DCHECK(arg != NULL);
359aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    ImageDump* state = reinterpret_cast<ImageDump*>(arg);
36078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    if (!state->InDumpSpace(obj)) {
36178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      return;
36278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
363916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
364916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes = obj->SizeOf();
365916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes;
366916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.object_bytes += object_bytes;
367916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    state->stats_.alignment_bytes += alignment_bytes;
368916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
36978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    std::string summary;
370d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    Class* obj_class = obj->GetClass();
371d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj_class->IsArrayClass()) {
372d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: %s length:%d\n", obj, PrettyDescriptor(obj_class).c_str(),
373d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    obj->AsArray()->GetLength());
374d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
37578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      Class* klass = obj->AsClass();
376d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.Class \"%s\" (", obj,
377d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    PrettyDescriptor(klass).c_str());
3783b6baaa203fa63f1522b2172a1645f90412afdaeElliott Hughes      std::ostringstream ss;
379d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      ss << klass->GetStatus() << ")\n";
380e10b6974d54f38001aee7bec518d45a7d4fb64c1Brian Carlstrom      summary += ss.str();
38178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else if (obj->IsField()) {
382d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.reflect.Field %s\n", obj,
383d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    PrettyField(obj->AsField()).c_str());
384d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsMethod()) {
385d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.reflect.Method %s\n", obj,
386d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    PrettyMethod(obj->AsMethod()).c_str());
387d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj_class->IsStringClass()) {
388d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: java.lang.String \"%s\"\n", obj,
389d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers                    obj->AsString()->ToModifiedUtf8().c_str());
39078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
391d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      StringAppendF(&summary, "%p: %s\n", obj, PrettyDescriptor(obj_class).c_str());
39278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
393d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    DumpFields(summary, obj, obj_class);
394d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    if (obj->IsObjectArray()) {
395d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      ObjectArray<Object>* obj_array = obj->AsObjectArray<Object>();
396d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      int32_t length = obj_array->GetLength();
397d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      for (int32_t i = 0; i < length; i++) {
398d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        Object* value = obj_array->Get(i);
399d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        size_t run = 0;
400d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t j = i + 1; j < length; j++) {
401d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          if (value == obj_array->Get(j)) {
402d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            run++;
403d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          } else {
404d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers            break;
405d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          }
406d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
407d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        if (run == 0) {
408d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          StringAppendF(&summary, "\t%d: ", i);
40978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        } else {
410d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          StringAppendF(&summary, "\t%d to %d: ", i, i + run);
411d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          i = i + run;
41278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom        }
413d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        Class* value_class = value == NULL ? obj_class->GetComponentType() : value->GetClass();
414d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        PrettyObjectValue(summary, value_class, value);
415d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
416d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsClass()) {
417d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      ObjectArray<Field>* sfields = obj->AsClass()->GetSFields();
418d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      if (sfields != NULL) {
419d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        summary += "\t\tSTATICS:\n";
420d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        for (int32_t i = 0; i < sfields->GetLength(); i++) {
421d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          Field* field = sfields->Get(i);
422d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers          PrintField(summary, field, NULL);
423d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        }
424d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      }
425d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    } else if (obj->IsMethod()) {
426d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      Method* method = obj->AsMethod();
427d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      if (method->IsNative()) {
428d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        DCHECK(method->GetGcMap() == NULL) << PrettyMethod(method);
429e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_EQ(0U, method->GetGcMapLength()) << PrettyMethod(method);
4303320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
431d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers      } else if (method->IsAbstract() || method->IsCalleeSaveMethod()) {
432d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        DCHECK(method->GetGcMap() == NULL) << PrettyMethod(method);
433e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_EQ(0U, method->GetGcMapLength()) << PrettyMethod(method);
4343320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom        DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method);
435916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      } else {
436e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK(method->GetGcMap() != NULL) << PrettyMethod(method);
437e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        DCHECK_NE(0U, method->GetGcMapLength()) << PrettyMethod(method);
438916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
439e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        size_t register_map_bytes = method->GetGcMapLength();
440e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        state->stats_.register_map_bytes += register_map_bytes;
441e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
442e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        size_t pc_mapping_table_bytes = method->GetMappingTableLength();
443e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom        state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes;
444916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
4456d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers        const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem();
446d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers        size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2;
447916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        state->stats_.dex_instruction_bytes += dex_instruction_bytes;
448e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom
449d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers        StringAppendF(&summary, "\t\tSIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n",
450e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom                      dex_instruction_bytes, register_map_bytes, pc_mapping_table_bytes);
45178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      }
45278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
453d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    std::string descriptor(ClassHelper(obj_class).GetDescriptor());
454d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    state->stats_.descriptor_to_bytes[descriptor] += object_bytes;
455d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers    state->stats_.descriptor_to_count[descriptor] += 1;
456d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers
45727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    state->os_ << summary << std::flush;
45878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
45927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom
46027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  bool InDumpSpace(const Object* object) {
46130fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers    return dump_space_.Contains(object);
46227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  }
463916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
464916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom public:
465916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  struct Stats {
466916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t file_bytes;
467916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
468916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t header_bytes;
469916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t object_bytes;
470916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t alignment_bytes;
471916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
472916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_code_bytes;
473916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t managed_to_native_code_bytes;
474916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t native_to_managed_code_bytes;
475916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
476916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t register_map_bytes;
477916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t pc_mapping_table_bytes;
478916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
479916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    size_t dex_instruction_bytes;
480916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
481916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    Stats()
482916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        : file_bytes(0),
483916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          header_bytes(0),
484916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          object_bytes(0),
485916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          alignment_bytes(0),
486916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_code_bytes(0),
487916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          managed_to_native_code_bytes(0),
488916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          native_to_managed_code_bytes(0),
489916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          register_map_bytes(0),
490916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          pc_mapping_table_bytes(0),
491916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom          dex_instruction_bytes(0) {}
492916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
493e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes    typedef std::map<std::string, size_t> TableBytes;
494916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    TableBytes descriptor_to_bytes;
495916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
496e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes    typedef std::map<std::string, size_t> TableCount;
497916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    TableCount descriptor_to_count;
498916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
499916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfFileBytes(size_t size) {
500916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100;
501916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
502916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
503916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    double PercentOfObjectBytes(size_t size) {
504916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100;
505916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
506916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
507916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    void Dump(std::ostream& os) {
508ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tfile_bytes = %zd\n", file_bytes);
509916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
510916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
511916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\tfile_bytes = header_bytes + object_bytes + alignment_bytes\n";
512ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\theader_bytes    = %10zd (%2.0f%% of file_bytes)\n",
513916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         header_bytes, PercentOfFileBytes(header_bytes));
514ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tobject_bytes    = %10zd (%2.0f%% of file_bytes)\n",
515916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         object_bytes, PercentOfFileBytes(object_bytes));
516ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\talignment_bytes = %10zd (%2.0f%% of file_bytes)\n",
517916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         alignment_bytes, PercentOfFileBytes(alignment_bytes));
518916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
519916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
520916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(file_bytes, header_bytes + object_bytes + alignment_bytes);
521916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
522916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\tobject_bytes = sum of descriptor_to_bytes values below:\n";
523916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      size_t object_bytes_total = 0;
524916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      typedef TableBytes::const_iterator It;  // TODO: C++0x auto
525916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      for (It it = descriptor_to_bytes.begin(), end = descriptor_to_bytes.end(); it != end; ++it) {
526955724179c6c739524f610023287f56b24dc31deElliott Hughes        const std::string& descriptor(it->first);
527916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        size_t bytes = it->second;
528916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        size_t count = descriptor_to_count[descriptor];
529916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        double average = static_cast<double>(bytes) / static_cast<double>(count);
530916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        double percent = PercentOfObjectBytes(bytes);
531ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes        os << StringPrintf("\t%32s %8zd bytes %6zd instances "
532916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           "(%3.0f bytes/instance) %2.0f%% of object_bytes\n",
533916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           descriptor.c_str(), bytes, count,
534916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                           average, percent);
535916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
536916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom        object_bytes_total += bytes;
537916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      }
538916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
539916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
540916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      CHECK_EQ(object_bytes, object_bytes_total);
541916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
542ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tmanaged_code_bytes           = %8zd (%2.0f%% of object_bytes)\n",
543916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         managed_code_bytes, PercentOfObjectBytes(managed_code_bytes));
544ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tmanaged_to_native_code_bytes = %8zd (%2.0f%% of object_bytes)\n",
545916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         managed_to_native_code_bytes,
546916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         PercentOfObjectBytes(managed_to_native_code_bytes));
547ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tnative_to_managed_code_bytes = %8zd (%2.0f%% of object_bytes)\n",
548916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         native_to_managed_code_bytes,
549916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         PercentOfObjectBytes(native_to_managed_code_bytes));
550916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
551916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
552916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
553ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tregister_map_bytes     = %7zd (%2.0f%% of object_bytes)\n",
554916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         register_map_bytes, PercentOfObjectBytes(register_map_bytes));
555ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tpc_mapping_table_bytes = %7zd (%2.0f%% of object_bytes)\n",
556916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         pc_mapping_table_bytes, PercentOfObjectBytes(pc_mapping_table_bytes));
557916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
558916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
559916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
560ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes      os << StringPrintf("\tdex_instruction_bytes = %zd\n", dex_instruction_bytes);
561916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << StringPrintf("\tmanaged_code_bytes expansion = %.2f\n",
562916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         static_cast<double>(managed_code_bytes)
563916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom                         / static_cast<double>(dex_instruction_bytes));
564916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << "\n";
565916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom      os << std::flush;
566916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom    }
567916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom  } stats_;
568916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom
569916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom private:
57027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  const Space& dump_space_;
57127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream& os_;
572d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes
573aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  DISALLOW_COPY_AND_ASSIGN(ImageDump);
57478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom};
57578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
57678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint oatdump(int argc, char** argv) {
57778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  // Skip over argv[0].
57878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argv++;
57978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  argc--;
58078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
58178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (argc == 0) {
582aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "No arguments specified\n");
58378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    usage();
58478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
58578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
586aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  const char* oat_filename = NULL;
58778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const char* image_filename = NULL;
58878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const char* boot_image_filename = NULL;
58958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  std::string host_prefix;
59027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  std::ostream* os = &std::cout;
59127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom  UniquePtr<std::ofstream> out;
59278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
59378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  for (int i = 0; i < argc; i++) {
59478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    const StringPiece option(argv[i]);
595a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom    if (option.starts_with("--oat-file=")) {
596a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom      oat_filename = option.substr(strlen("--oat-file=")).data();
597aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    } else if (option.starts_with("--image=")) {
59878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      image_filename = option.substr(strlen("--image=")).data();
599e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom    } else if (option.starts_with("--boot-image=")) {
600e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom      boot_image_filename = option.substr(strlen("--boot-image=")).data();
60158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    } else if (option.starts_with("--host-prefix=")) {
60258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom      host_prefix = option.substr(strlen("--host-prefix=")).data();
60327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom    } else if (option.starts_with("--output=")) {
60427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      const char* filename = option.substr(strlen("--output=")).data();
60527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      out.reset(new std::ofstream(filename));
60627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      if (!out->good()) {
607aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom        fprintf(stderr, "Failed to open output filename %s\n", filename);
60827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom        usage();
60927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      }
61027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom      os = out.get();
61178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    } else {
612aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Unknown argument %s\n", option.data());
61378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom      usage();
61478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    }
61578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
61678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
617aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename == NULL && oat_filename == NULL) {
618362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified\n");
619362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
62078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
62178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
622aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename != NULL && oat_filename != NULL) {
623362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    fprintf(stderr, "Either --image or --oat must be specified but not both\n");
624362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes    return EXIT_FAILURE;
625aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
626aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
627aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (oat_filename != NULL) {
628a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    const OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, NULL);
629aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    if (oat_file == NULL) {
630aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      fprintf(stderr, "Failed to open oat file from %s\n", oat_filename);
631aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom      return EXIT_FAILURE;
632aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    }
633a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom    OatDump::Dump(oat_filename, *os, *oat_file);
634aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    return EXIT_SUCCESS;
635aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
636aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom
63778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  Runtime::Options options;
63878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string image_option;
639e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string oat_option;
64078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  std::string boot_image_option;
641e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom  std::string boot_oat_option;
64258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (boot_image_filename != NULL) {
64358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += "-Ximage:";
64458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    boot_image_option += boot_image_filename;
64558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL)));
64658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  }
647aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  if (image_filename != NULL) {
648aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += "-Ximage:";
649aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    image_option += image_filename;
650aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
651aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  }
65258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom
65358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom  if (!host_prefix.empty()) {
65458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom    options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
65578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
65678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
65778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  UniquePtr<Runtime> runtime(Runtime::Create(options, false));
65878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (runtime.get() == NULL) {
659aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Failed to create runtime\n");
66078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
66178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
66278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
66330fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers  ImageSpace* image_space = Heap::GetSpaces()[Heap::GetSpaces().size()-2]->AsImageSpace();
66478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  CHECK(image_space != NULL);
66578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  const ImageHeader& image_header = image_space->GetImageHeader();
66678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  if (!image_header.IsValid()) {
667aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom    fprintf(stderr, "Invalid image header %s\n", image_filename);
66878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom    return EXIT_FAILURE;
66978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  }
670aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom  ImageDump::Dump(image_filename, host_prefix, *os, *image_space, image_header);
67178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return EXIT_SUCCESS;
67278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
67378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
67478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom} // namespace art
67578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom
67678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint main(int argc, char** argv) {
67778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom  return art::oatdump(argc, argv);
67878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}
679