oatdump.cc revision f8bbb8448c733e9e3ad43aad69774c37888329b1
12faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes/* 22faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Copyright (C) 2011 The Android Open Source Project 32faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 42faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 52faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * you may not use this file except in compliance with the License. 62faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * You may obtain a copy of the License at 72faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 82faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 92faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * 102faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * Unless required by applicable law or agreed to in writing, software 112faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 122faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * See the License for the specific language governing permissions and 142faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes * limitations under the License. 152faa5f1271587cda765f26bcf2951065300a01ffElliott Hughes */ 1678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 1778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <stdio.h> 1878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <stdlib.h> 1978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 2027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <fstream> 2127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom#include <iostream> 22e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes#include <map> 2378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <string> 2478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include <vector> 2578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 2678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "class_linker.h" 273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers#include "context.h" 28e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes#include "dex_instruction.h" 293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers#include "dex_verifier.h" 303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers#include "disassembler.h" 31916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom#include "file.h" 3278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "image.h" 336d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers#include "object_utils.h" 34e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes#include "os.h" 3578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "runtime.h" 3678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "space.h" 3778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom#include "stringpiece.h" 3878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 3978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromnamespace art { 4078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 4178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromstatic void usage() { 4278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom fprintf(stderr, 4378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom "Usage: oatdump [options] ...\n" 4429e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom " Example: oatdump --image=$ANDROID_PRODUCT_OUT/system/framework/boot.art --host-prefix=$ANDROID_PRODUCT_OUT\n" 4529e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom " Example: adb shell oatdump --image=/system/framework/boot.art\n" 4678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom "\n"); 4778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom fprintf(stderr, 48a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom " --oat-file=<file.oat>: specifies an input oat filename.\n" 4929e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom " Example: --image=/system/framework/boot.oat\n" 50aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom "\n"); 51aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom fprintf(stderr, 52aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom " --image=<file.art>: specifies an input image filename.\n" 5329e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom " Example: --image=/system/framework/boot.art\n" 54e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom "\n"); 5578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom fprintf(stderr, 56e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom " --boot-image=<file.art>: provide the image file for the boot class path.\n" 5729e7ac74a3f9aec192099fec381baadaa55730adBrian Carlstrom " Example: --boot-image=/system/framework/boot.art\n" 58e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom "\n"); 59e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom fprintf(stderr, 6058ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom " --host-prefix may be used to translate host paths to target paths during\n" 6158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom " cross compilation.\n" 6258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom " Example: --host-prefix=out/target/product/crespo\n" 63fe487d0c789b94e75c93a2b799f1955c3e4edb10Brian Carlstrom " Default: $ANDROID_PRODUCT_OUT\n" 6478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom "\n"); 6527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom fprintf(stderr, 6627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom " --output=<file> may be used to send the output to a file.\n" 6727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom " Example: --output=/tmp/oatdump.txt\n" 6827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom "\n"); 6978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom exit(EXIT_FAILURE); 7078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom} 7178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 72ff1ed4770bf7ff024a807b9f909b1a26abb78341Ian Rogersconst char* image_roots_descriptions_[] = { 7378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom "kJniStubArray", 74e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom "kAbstractMethodErrorStubArray", 75ad25ac568407ceb14334e8551dd1c4dd0fd6993cIan Rogers "kStaticResolutionStubArray", 761cb0a1dfc32531c79a968aeac26ccb5525862497Ian Rogers "kUnknownMethodResolutionStubArray", 771984651929744dd603fd082e23eacd877b9bc177Ian Rogers "kResolutionMethod", 78e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom "kCalleeSaveMethod", 79aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom "kRefsOnlySaveMethod", 80aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom "kRefsAndArgsSaveMethod", 81e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom "kOatLocation", 8258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom "kDexCaches", 8334f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom "kClassRoots", 8478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}; 8578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 86e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughesclass OatDumper { 87aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom public: 883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers explicit OatDumper(const OatFile& oat_file) : oat_file_(oat_file), 89a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes oat_dex_files_(oat_file.GetOatDexFiles()), 90a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes disassembler_(Disassembler::Create(oat_file_.GetOatHeader().GetInstructionSet())) { 913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers AddAllOffsets(); 923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void Dump(std::ostream& os) { 953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const OatHeader& oat_header = oat_file_.GetOatHeader(); 96aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 97aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << "MAGIC:\n"; 98aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << oat_header.GetMagic() << "\n\n"; 99aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 100aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << "CHECKSUM:\n"; 101ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes os << StringPrintf("0x%08x\n\n", oat_header.GetChecksum()); 102aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 103a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes os << "INSTRUCTION SET:\n"; 104a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes os << oat_header.GetInstructionSet() << "\n\n"; 105a72ec820f8cb8e04b0ba87a62e36b05a2c92ef36Elliott Hughes 106aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << "DEX FILE COUNT:\n"; 107aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << oat_header.GetDexFileCount() << "\n\n"; 108aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 109aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << "EXECUTABLE OFFSET:\n"; 110ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset()); 111aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 11230fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers os << "BEGIN:\n"; 1133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << reinterpret_cast<const void*>(oat_file_.Begin()) << "\n\n"; 114aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 11530fab40ee5a07af6b8c3b6b0e9438071695a57f4Ian Rogers os << "END:\n"; 1163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << reinterpret_cast<const void*>(oat_file_.End()) << "\n\n"; 117aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 118aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << std::flush; 119aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 1203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t i = 0; i < oat_dex_files_.size(); i++) { 1213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i]; 1223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers CHECK(oat_dex_file != NULL); 1233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpOatDexFile(os, *oat_dex_file); 1243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 1253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 1263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 1273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t ComputeSize(const void* oat_data) { 1283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (reinterpret_cast<const byte*>(oat_data) < oat_file_.Begin() || 1293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers reinterpret_cast<const byte*>(oat_data) > oat_file_.End()) { 1303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return 0; // Address not in oat file 1313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 1323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint32_t begin_offset = reinterpret_cast<size_t>(oat_data) - 1333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers reinterpret_cast<size_t>(oat_file_.Begin()); 1343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers typedef std::set<uint32_t>::iterator It; 1353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers It it = offsets_.upper_bound(begin_offset); 1363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers CHECK(it != offsets_.end()); 1373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint32_t end_offset = *it; 1383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return end_offset - begin_offset; 1393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 140e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 141f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom InstructionSet GetInstructionSet() { 142f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom return oat_file_.GetOatHeader().GetInstructionSet(); 143f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom } 144f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom 1453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const void* GetOatCode(Method* m) { 1463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers MethodHelper mh(m); 1473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t i = 0; i < oat_dex_files_.size(); i++) { 1483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i]; 149aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CHECK(oat_dex_file != NULL); 1503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers UniquePtr<const DexFile> dex_file(oat_dex_file->OpenDexFile()); 1513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (dex_file.get() != NULL) { 1523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint32_t class_def_index; 1533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers bool found = dex_file->FindClassDefIndex(mh.GetDeclaringClassDescriptor(), class_def_index); 1543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (found) { 1553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const OatFile::OatClass* oat_class = oat_dex_file->GetOatClass(class_def_index); 1563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers CHECK(oat_class != NULL); 1573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t method_index = m->GetMethodIndex(); 1583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return oat_class->GetOatMethod(method_index).GetCode(); 1593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 1603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 161aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 1623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return NULL; 163aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 164aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 165aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom private: 1663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void AddAllOffsets() { 167e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes // We don't know the length of the code for each method, but we need to know where to stop 168e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes // when disassembling. What we do know is that a region of code will be followed by some other 169e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes // region, so if we keep a sorted sequence of the start of each region, we can infer the length 170e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes // of a piece of code by using upper_bound to find the start of the next region. 1713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t i = 0; i < oat_dex_files_.size(); i++) { 1723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i]; 173e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes CHECK(oat_dex_file != NULL); 174e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes UniquePtr<const DexFile> dex_file(oat_dex_file->OpenDexFile()); 175e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes if (dex_file.get() == NULL) { 1763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers continue; 177e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 1783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers offsets_.insert(reinterpret_cast<uint32_t>(&dex_file->GetHeader())); 179e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) { 180e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); 181e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file->GetOatClass(class_def_index)); 182e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const byte* class_data = dex_file->GetClassData(class_def); 183e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes if (class_data != NULL) { 184e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes ClassDataItemIterator it(*dex_file, class_data); 185e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes SkipAllFields(it); 186e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes uint32_t class_method_index = 0; 187e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes while (it.HasNextDirectMethod()) { 188e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes AddOffsets(oat_class->GetOatMethod(class_method_index++)); 189e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes it.Next(); 190e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 191e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes while (it.HasNextVirtualMethod()) { 192e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes AddOffsets(oat_class->GetOatMethod(class_method_index++)); 193e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes it.Next(); 194e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 195e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 196e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 197e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 198e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 199e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes // If the last thing in the file is code for a method, there won't be an offset for the "next" 200e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes // thing. Instead of having a special case in the upper_bound code, let's just add an entry 201e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes // for the end of the file. 2023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers offsets_.insert(static_cast<uint32_t>(oat_file_.End() - oat_file_.Begin())); 203e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 204e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 205e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes void AddOffsets(const OatFile::OatMethod& oat_method) { 20695ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom uint32_t code_offset = oat_method.GetCodeOffset(); 20795ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom if (oat_file_.GetOatHeader().GetInstructionSet() == kThumb2) { 20895ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom code_offset &= ~0x1; 20995ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom } 21095ba0dc516531776813c426e85ce868ead564a7bBrian Carlstrom offsets_.insert(code_offset); 211e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes offsets_.insert(oat_method.GetMappingTableOffset()); 212e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes offsets_.insert(oat_method.GetVmapTableOffset()); 213e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes offsets_.insert(oat_method.GetGcMapOffset()); 214e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes offsets_.insert(oat_method.GetInvokeStubOffset()); 215e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 216e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 2173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void DumpOatDexFile(std::ostream& os, const OatFile::OatDexFile& oat_dex_file) { 218aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << "OAT DEX FILE:\n"; 219a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom os << StringPrintf("location: %s\n", oat_dex_file.GetDexFileLocation().c_str()); 220ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes os << StringPrintf("checksum: 0x%08x\n", oat_dex_file.GetDexFileLocationChecksum()); 221a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom UniquePtr<const DexFile> dex_file(oat_dex_file.OpenDexFile()); 222a004aa933a58428489e42d77f707c2b063b73747Brian Carlstrom if (dex_file.get() == NULL) { 223aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << "NOT FOUND\n\n"; 224aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom return; 225aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 226aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom for (size_t class_def_index = 0; class_def_index < dex_file->NumClassDefs(); class_def_index++) { 227aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); 228aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom const char* descriptor = dex_file->GetClassDescriptor(class_def); 229aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom UniquePtr<const OatFile::OatClass> oat_class(oat_dex_file.GetOatClass(class_def_index)); 230aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom CHECK(oat_class.get() != NULL); 231ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes os << StringPrintf("%zd: %s (type_idx=%d) (", class_def_index, descriptor, class_def.class_idx_) 232e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom << oat_class->GetStatus() << ")\n"; 2333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpOatClass(os, *oat_class.get(), *(dex_file.get()), class_def); 234aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 235aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 236aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << std::flush; 237aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 238aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 239e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes static void SkipAllFields(ClassDataItemIterator& it) { 2400571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextStaticField()) { 2410571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 242aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 2430571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextInstanceField()) { 2440571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 245aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 246e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 247aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 2483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void DumpOatClass(std::ostream& os, const OatFile::OatClass& oat_class, const DexFile& dex_file, 2493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const DexFile::ClassDef& class_def) { 250e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const byte* class_data = dex_file.GetClassData(class_def); 251e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes if (class_data == NULL) { // empty class such as a marker interface? 252e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes return; 253e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 254e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes ClassDataItemIterator it(dex_file, class_data); 255e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes SkipAllFields(it); 256e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 257e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes uint32_t class_method_index = 0; 2580571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextDirectMethod()) { 259e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_index); 2603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpOatMethod(os, class_method_index, oat_method, dex_file, 2613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers it.GetMemberIndex(), it.GetMethodCodeItem()); 262e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes class_method_index++; 2630571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 264aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 2650571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers while (it.HasNextVirtualMethod()) { 266e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const OatFile::OatMethod oat_method = oat_class.GetOatMethod(class_method_index); 2673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpOatMethod(os, class_method_index, oat_method, dex_file, 2683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers it.GetMemberIndex(), it.GetMethodCodeItem()); 269e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes class_method_index++; 2700571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers it.Next(); 271aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 2720571d357843c53e042f370f5f2c2e9aa3fe803a9Ian Rogers DCHECK(!it.HasNext()); 273aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom os << std::flush; 274aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 275e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 2763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void DumpOatMethod(std::ostream& os, uint32_t class_method_index, 277e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const OatFile::OatMethod& oat_method, const DexFile& dex_file, 278e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes uint32_t dex_method_idx, const DexFile::CodeItem* code_item) { 279e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const DexFile::MethodId& method_id = dex_file.GetMethodId(dex_method_idx); 280aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom const char* name = dex_file.GetMethodName(method_id); 281955724179c6c739524f610023287f56b24dc31deElliott Hughes std::string signature(dex_file.GetMethodSignature(method_id)); 282e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes os << StringPrintf("\t%d: %s %s (dex_method_idx=%d)\n", 283e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes class_method_index, name, signature.c_str(), dex_method_idx); 284ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes os << StringPrintf("\t\tcode: %p (offset=0x%08x)\n", 285ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom oat_method.GetCode(), oat_method.GetCodeOffset()); 286ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes os << StringPrintf("\t\tframe_size_in_bytes: %zd\n", 287ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom oat_method.GetFrameSizeInBytes()); 2883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << StringPrintf("\t\tcore_spill_mask: 0x%08x", 289ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom oat_method.GetCoreSpillMask()); 2903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpSpillMask(os, oat_method.GetCoreSpillMask(), false); 2913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << StringPrintf("\n\t\tfp_spill_mask: 0x%08x", 292ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom oat_method.GetFpSpillMask()); 2933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpSpillMask(os, oat_method.GetFpSpillMask(), true); 2943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << StringPrintf("\n\t\tmapping_table: %p (offset=0x%08x)\n", 295ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom oat_method.GetMappingTable(), oat_method.GetMappingTableOffset()); 2963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpMappingTable(os, oat_method); 297ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes os << StringPrintf("\t\tvmap_table: %p (offset=0x%08x)\n", 298ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom oat_method.GetVmapTable(), oat_method.GetVmapTableOffset()); 2993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpVmap(os, oat_method.GetVmapTable(), oat_method.GetCoreSpillMask(), 3003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers oat_method.GetFpSpillMask()); 301ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes os << StringPrintf("\t\tgc_map: %p (offset=0x%08x)\n", 302e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom oat_method.GetGcMap(), oat_method.GetGcMapOffset()); 3033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpGcMap(os, oat_method.GetGcMap()); 304ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes os << StringPrintf("\t\tinvoke_stub: %p (offset=0x%08x)\n", 305ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom oat_method.GetInvokeStub(), oat_method.GetInvokeStubOffset()); 306f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom os << "\t\tCODE: (size=" << oat_method.GetCodeSize() << ")\n"; 3073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpCode(os, oat_method.GetCode(), oat_method.GetMappingTable(), dex_file, code_item); 308f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom os << "\t\tINVOKE STUB: (size=" << oat_method.GetInvokeStubSize() << ")\n"; 3093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpCode(os, reinterpret_cast<const void*>(oat_method.GetInvokeStub()), NULL, dex_file, NULL); 3103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 3123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void DumpSpillMask(std::ostream& os, uint32_t spill_mask, bool is_float) { 3133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (spill_mask == 0) { 3143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return; 3153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << " ("; 3173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t i = 0; i < 32; i++) { 3183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if ((spill_mask & (1 << i)) != 0) { 3193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (is_float) { 3203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "fr" << i; 3213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } else { 3223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "r" << i; 3233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers spill_mask ^= 1 << i; // clear bit 3253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (spill_mask != 0) { 3263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << ", "; 3273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } else { 3283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers break; 3293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << ")"; 3333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 3353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void DumpVmap(std::ostream& os, const uint16_t* raw_table, uint32_t core_spill_mask, 3363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint32_t fp_spill_mask) { 3373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (raw_table == NULL) { 3383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return; 3393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const VmapTable vmap_table(raw_table); 3413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers bool first = true; 3423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "\t\t\t"; 3433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t i = 0; i < vmap_table.size(); i++) { 3443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint16_t dex_reg = vmap_table[i]; 3453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t matches = 0; 3463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t spill_shifts = 0; 3473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint32_t spill_mask = core_spill_mask; 3483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers bool processing_fp = false; 3493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers while (matches != (i + 1)) { 3503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (spill_mask == 0) { 3513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers CHECK(!processing_fp); 3523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers spill_mask = fp_spill_mask; 3533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers processing_fp = true; 3543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers matches += spill_mask & 1; // Add 1 if the low bit is set 3563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers spill_mask >>= 1; 3573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers spill_shifts++; 3583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t arm_reg = spill_shifts - 1; // wind back one as we want the last match 3603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << (first ? "v" : ", v") << dex_reg; 3613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (arm_reg < 16) { 3623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "/r" << arm_reg; 3633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } else { 3643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "/fr" << (arm_reg - 16); 3653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first) { 3673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers first = false; 3683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << std::endl; 3713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 3733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void DumpGcMap(std::ostream& os, const uint8_t* gc_map_raw) { 3743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (gc_map_raw == NULL) { 3753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return; 3763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint32_t gc_map_length = (gc_map_raw[0] << 24) | (gc_map_raw[1] << 16) | 3783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers (gc_map_raw[2] << 8) | (gc_map_raw[3] << 0); 3793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers verifier::PcToReferenceMap map(gc_map_raw + sizeof(uint32_t), gc_map_length); 3803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t entry = 0; entry < map.NumEntries(); entry++) { 3813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << StringPrintf("\t\t\t0x%04x", map.GetPC(entry)); 3823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t num_regs = map.RegWidth() * 8; 3833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const uint8_t* reg_bitmap = map.GetBitMap(entry); 3843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers bool first = true; 3853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t reg = 0; reg < num_regs; reg++) { 3863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (((reg_bitmap[reg / 8] >> (reg % 8)) & 0x01) != 0) { 3873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first) { 3883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << " v" << reg; 3893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers first = false; 3903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } else { 3913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << ", v" << reg; 3923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 3953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << std::endl; 3963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 397aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 398e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 3993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void DumpMappingTable(std::ostream& os, const OatFile::OatMethod& oat_method) { 400e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const uint32_t* raw_table = oat_method.GetMappingTable(); 401e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const void* code = oat_method.GetCode(); 402e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes if (raw_table == NULL || code == NULL) { 403e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes return; 404e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 405e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 406e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes uint32_t length = *raw_table; 407e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes ++raw_table; 408e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 4093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "\t\t{"; 410e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes for (size_t i = 0; i < length; i += 2) { 4113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code) + raw_table[i]; 412e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes uint32_t dex_pc = raw_table[i + 1]; 4133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << StringPrintf("%p -> 0x%04x", native_pc, dex_pc); 4143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (i + 2 < length) { 4153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << ", "; 4163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 4173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 4183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "}" << std::endl << std::flush; 4193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 4203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 4213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void DumpCode(std::ostream& os, const void* code, const uint32_t* raw_mapping_table, 4223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const DexFile& dex_file, const DexFile::CodeItem* code_item) { 4233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (code == NULL) { 4243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return; 4253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 4263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 4273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (raw_mapping_table == NULL) { 4283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers // code but no mapping table is most likely caused by code created by the JNI compiler 4293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code); 4303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const uint8_t* oat_begin = reinterpret_cast<const uint8_t*>(oat_file_.Begin()); 4313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint32_t last_offset = static_cast<uint32_t>(native_pc - oat_begin); 4323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 4333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers typedef std::set<uint32_t>::iterator It; 4343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers It it = offsets_.upper_bound(last_offset); 4353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers CHECK(it != offsets_.end()); 4363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const uint8_t* end_native_pc = reinterpret_cast<const uint8_t*>(oat_begin) + *it; 4373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers CHECK(native_pc < end_native_pc); 4383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 4393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers disassembler_->Dump(os, native_pc, end_native_pc); 4403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return; 4413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 4423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 4433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint32_t length = *raw_mapping_table; 4443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers ++raw_mapping_table; 4453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 4463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t i = 0; i < length; i += 2) { 4473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers uint32_t dex_pc = raw_mapping_table[i + 1]; 448e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const Instruction* instruction = Instruction::At(&code_item->insns_[dex_pc]); 449e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes os << StringPrintf("\t\t0x%04x: %s\n", dex_pc, instruction->DumpString(&dex_file).c_str()); 450e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 4513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const uint8_t* native_pc = reinterpret_cast<const uint8_t*>(code) + raw_mapping_table[i]; 452e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes const uint8_t* end_native_pc = NULL; 453e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes if (i + 2 < length) { 4543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers end_native_pc = reinterpret_cast<const uint8_t*>(code) + raw_mapping_table[i + 2]; 455e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } else { 4563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const uint8_t* oat_begin = reinterpret_cast<const uint8_t*>(oat_file_.Begin()); 457e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes uint32_t last_offset = static_cast<uint32_t>(native_pc - oat_begin); 458e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 459e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes typedef std::set<uint32_t>::iterator It; 460ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes It it = offsets_.upper_bound(last_offset); 461e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes CHECK(it != offsets_.end()); 462e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes end_native_pc = reinterpret_cast<const uint8_t*>(oat_begin) + *it; 463e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 464ed2adb6158ffbe85c89aa5c9892a35bafa5006cdElliott Hughes CHECK(native_pc < end_native_pc); 4653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers disassembler_->Dump(os, native_pc, end_native_pc); 466e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 467e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes } 468e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes 4693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const OatFile& oat_file_; 4703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers std::vector<const OatFile::OatDexFile*> oat_dex_files_; 471e3c845cdb5884e770287a5c0c65c8bb64733c388Elliott Hughes std::set<uint32_t> offsets_; 4723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers UniquePtr<Disassembler> disassembler_; 473aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom}; 474aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 4753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogersclass ImageDumper { 47627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom public: 4773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers explicit ImageDumper(std::ostream& os, const std::string& image_filename, 4783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const std::string& host_prefix, Space& image_space, 4793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const ImageHeader& image_header) : os_(os), 4803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers image_filename_(image_filename), host_prefix_(host_prefix), 4813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers image_space_(image_space), image_header_(image_header) { 4823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 48327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 4843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void Dump() { 4853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "MAGIC:\n"; 4863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << image_header_.GetMagic() << "\n\n"; 487e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 4883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "IMAGE BEGIN:\n"; 4893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << reinterpret_cast<void*>(image_header_.GetImageBegin()) << "\n\n"; 490aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 4913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "OAT CHECKSUM:\n"; 4923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << StringPrintf("0x%08x\n\n", image_header_.GetOatChecksum()); 493916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 4943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "OAT BEGIN:\n"; 4953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << reinterpret_cast<void*>(image_header_.GetOatBegin()) << "\n\n"; 496aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 4973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "OAT END:\n"; 4983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << reinterpret_cast<void*>(image_header_.GetOatEnd()) << "\n\n"; 4993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 5003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "ROOTS:\n"; 5013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << reinterpret_cast<void*>(image_header_.GetImageRoots()) << "\n"; 502418d20fc407052d4152157f61e7453359f902383Elliott Hughes CHECK_EQ(arraysize(image_roots_descriptions_), size_t(ImageHeader::kImageRootsMax)); 50327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom for (int i = 0; i < ImageHeader::kImageRootsMax; i++) { 50427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom ImageHeader::ImageRoot image_root = static_cast<ImageHeader::ImageRoot>(i); 50534f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom const char* image_root_description = image_roots_descriptions_[i]; 5063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers Object* image_root_object = image_header_.GetImageRoot(image_root); 5073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << StringPrintf("%s: %p\n", image_root_description, image_root_object); 50834f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom if (image_root_object->IsObjectArray()) { 50934f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom // TODO: replace down_cast with AsObjectArray (g++ currently has a problem with this) 51034f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom ObjectArray<Object>* image_root_object_array 51134f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom = down_cast<ObjectArray<Object>*>(image_root_object); 51234f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom // = image_root_object->AsObjectArray<Object>(); 51334f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom for (int i = 0; i < image_root_object_array->GetLength(); i++) { 514d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Object* value = image_root_object_array->Get(i); 515d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (value != NULL) { 5163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "\t" << i << ": "; 517d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers std::string summary; 518d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers PrettyObjectValue(summary, value->GetClass(), value); 5193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << summary; 520d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else { 5213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << StringPrintf("\t%d: null\n", i); 522d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 52334f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom } 52434f426c49ac2de8cea70acef6b9ecdd8e62209d2Brian Carlstrom } 52527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 5263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "\n"; 52727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 5284dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom os_ << "OAT LOCATION:\n" << std::flush; 529aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 5303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers Object* oat_location_object = image_header_.GetImageRoot(ImageHeader::kOatLocation); 5313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers std::string oat_location(oat_location_object->AsString()->ToModifiedUtf8()); 5324dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom os_ << oat_location; 5333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (!host_prefix_.empty()) { 5343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers oat_location = host_prefix_ + oat_location; 5353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << " (" << oat_location << ")"; 536aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 5374dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom os_ << "\n"; 538ae826983f7903bc0a6bbbe8426bf393fb2f6d747Brian Carlstrom const OatFile* oat_file = class_linker->FindOatFileFromOatLocation(oat_location); 539aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom if (oat_file == NULL) { 5404dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom os_ << "NOT FOUND\n"; 541aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom return; 542aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 5434dcbffb3c6e8757d127dede32c8efa6c04e44a70Brian Carlstrom os_ << "\n"; 544aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 5453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers stats_.oat_file_bytes = oat_file->Size(); 54678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 5473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers oat_dumper_.reset(new OatDumper(*oat_file)); 5483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 5493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "OBJECTS:\n" << std::flush; 550b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes HeapBitmap* heap_bitmap = Runtime::Current()->GetHeap()->GetLiveBits(); 5513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DCHECK(heap_bitmap != NULL); 5523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers heap_bitmap->Walk(ImageDumper::Callback, this); 5533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "\n"; 5543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 5553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "STATS:\n" << std::flush; 5563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers UniquePtr<File> file(OS::OpenFile(image_filename_.c_str(), false)); 5573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers stats_.file_bytes = file->Length(); 5583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t header_bytes = sizeof(ImageHeader); 5593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers stats_.header_bytes = header_bytes; 5603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t alignment_bytes = RoundUp(header_bytes, kObjectAlignment) - header_bytes; 5613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers stats_.alignment_bytes += alignment_bytes; 5623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers stats_.Dump(os_); 5633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << "\n"; 56427ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 5653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os_ << std::flush; 5663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 5673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers oat_dumper_->Dump(os_); 5683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 569d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes 5703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers private: 57127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 572d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers static void PrettyObjectValue(std::string& summary, Class* type, Object* value) { 573d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers CHECK(type != NULL); 574d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (value == NULL) { 575d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "null %s\n", PrettyDescriptor(type).c_str()); 576d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (type->IsStringClass()) { 577d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers String* string = value->AsString(); 578d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p String: \"%s\"\n", string, string->ToModifiedUtf8().c_str()); 579d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (value->IsClass()) { 580d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Class* klass = value->AsClass(); 581d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p Class: %s\n", klass, PrettyDescriptor(klass).c_str()); 582d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (value->IsField()) { 583d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Field* field = value->AsField(); 584d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p Field: %s\n", field, PrettyField(field).c_str()); 585d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (value->IsMethod()) { 586d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Method* method = value->AsMethod(); 587d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p Method: %s\n", method, PrettyMethod(method).c_str()); 588d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else { 589d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p %s\n", value, PrettyDescriptor(type).c_str()); 590d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 591d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 592d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers 593d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers static void PrintField(std::string& summary, Field* field, Object* obj) { 594d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers FieldHelper fh(field); 595d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Class* type = fh.GetType(); 596d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "\t%s: ", fh.GetName()); 597d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (type->IsPrimitiveLong()) { 598d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%lld (0x%llx)\n", field->Get64(obj), field->Get64(obj)); 599d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (type->IsPrimitiveDouble()) { 600d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%f (%a)\n", field->GetDouble(obj), field->GetDouble(obj)); 601d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (type->IsPrimitiveFloat()) { 602d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%f (%a)\n", field->GetFloat(obj), field->GetFloat(obj)); 603d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (type->IsPrimitive()){ 604d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%d (0x%x)\n", field->Get32(obj), field->Get32(obj)); 605d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else { 606d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Object* value = field->GetObj(obj); 607d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers PrettyObjectValue(summary, type, value); 608d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 609d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 610d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers 611d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers static void DumpFields(std::string& summary, Object* obj, Class* klass) { 612d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Class* super = klass->GetSuperClass(); 613d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (super != NULL) { 614d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers DumpFields(summary, obj, super); 615d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 616d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers ObjectArray<Field>* fields = klass->GetIFields(); 617d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (fields != NULL) { 618d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers for (int32_t i = 0; i < fields->GetLength(); i++) { 619d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Field* field = fields->Get(i); 620d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers PrintField(summary, field, obj); 621d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 622d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 623d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 624d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers 6253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers bool InDumpSpace(const Object* object) { 6263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return image_space_.Contains(object); 627f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom } 6283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 629f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom const void* GetOatCodeBegin(Method* m) { 6303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers Runtime* runtime = Runtime::Current(); 6313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const void* code = m->GetCode(); 632fb6adba0d5d5505610fbd325e7911db700a2f1e8Ian Rogers if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) { 6333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers code = oat_dumper_->GetOatCode(m); 6343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 635f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom if (oat_dumper_->GetInstructionSet() == kThumb2) { 636f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom code = reinterpret_cast<void*>(reinterpret_cast<uint32_t>(code) & ~0x1); 637f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom } 6383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return code; 6393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 6403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 641f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom uint32_t GetOatCodeSize(Method* m) { 642f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom const uint32_t* oat_code_begin = reinterpret_cast<const uint32_t*>(GetOatCodeBegin(m)); 643f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom if (oat_code_begin == NULL) { 644f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom return 0; 645f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom } 646f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom return oat_code_begin[-1]; 647f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom } 648f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom 649f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom const void* GetOatCodeEnd(Method* m) { 650f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom const uint8_t* oat_code_begin = reinterpret_cast<const uint8_t*>(GetOatCodeBegin(m)); 651f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom if (oat_code_begin == NULL) { 652f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom return NULL; 653f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom } 654f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom return oat_code_begin + GetOatCodeSize(m); 655f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom } 656f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom 65778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom static void Callback(Object* obj, void* arg) { 65878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom DCHECK(obj != NULL); 65978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom DCHECK(arg != NULL); 6603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers ImageDumper* state = reinterpret_cast<ImageDumper*>(arg); 66178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom if (!state->InDumpSpace(obj)) { 66278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom return; 66378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 664916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 665916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t object_bytes = obj->SizeOf(); 666916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t alignment_bytes = RoundUp(object_bytes, kObjectAlignment) - object_bytes; 667916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom state->stats_.object_bytes += object_bytes; 668916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom state->stats_.alignment_bytes += alignment_bytes; 669916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 67078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom std::string summary; 671d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Class* obj_class = obj->GetClass(); 672d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (obj_class->IsArrayClass()) { 673d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p: %s length:%d\n", obj, PrettyDescriptor(obj_class).c_str(), 674d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers obj->AsArray()->GetLength()); 675d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (obj->IsClass()) { 67678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom Class* klass = obj->AsClass(); 677d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p: java.lang.Class \"%s\" (", obj, 678d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers PrettyDescriptor(klass).c_str()); 6793b6baaa203fa63f1522b2172a1645f90412afdaeElliott Hughes std::ostringstream ss; 680d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers ss << klass->GetStatus() << ")\n"; 681e10b6974d54f38001aee7bec518d45a7d4fb64c1Brian Carlstrom summary += ss.str(); 68278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } else if (obj->IsField()) { 683d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p: java.lang.reflect.Field %s\n", obj, 684d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers PrettyField(obj->AsField()).c_str()); 685d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (obj->IsMethod()) { 686d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p: java.lang.reflect.Method %s\n", obj, 687d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers PrettyMethod(obj->AsMethod()).c_str()); 688d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (obj_class->IsStringClass()) { 689d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p: java.lang.String \"%s\"\n", obj, 690d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers obj->AsString()->ToModifiedUtf8().c_str()); 69178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } else { 692d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "%p: %s\n", obj, PrettyDescriptor(obj_class).c_str()); 69378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 694d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers DumpFields(summary, obj, obj_class); 695d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (obj->IsObjectArray()) { 696d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers ObjectArray<Object>* obj_array = obj->AsObjectArray<Object>(); 697d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers int32_t length = obj_array->GetLength(); 698d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers for (int32_t i = 0; i < length; i++) { 699d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Object* value = obj_array->Get(i); 700d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers size_t run = 0; 701d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers for (int32_t j = i + 1; j < length; j++) { 702d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (value == obj_array->Get(j)) { 703d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers run++; 704d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else { 705d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers break; 706d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 707d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 708d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (run == 0) { 709d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "\t%d: ", i); 71078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } else { 711c1051ae94c5bd45367152a603f3946a933ad91faElliott Hughes StringAppendF(&summary, "\t%d to %zd: ", i, i + run); 712d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers i = i + run; 71378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 714d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Class* value_class = value == NULL ? obj_class->GetComponentType() : value->GetClass(); 715d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers PrettyObjectValue(summary, value_class, value); 716d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 717d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (obj->IsClass()) { 718d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers ObjectArray<Field>* sfields = obj->AsClass()->GetSFields(); 719d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (sfields != NULL) { 720d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers summary += "\t\tSTATICS:\n"; 721d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers for (int32_t i = 0; i < sfields->GetLength(); i++) { 722d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Field* field = sfields->Get(i); 723d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers PrintField(summary, field, NULL); 724d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 725d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } 726d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers } else if (obj->IsMethod()) { 727d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers Method* method = obj->AsMethod(); 728d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers if (method->IsNative()) { 729d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers DCHECK(method->GetGcMap() == NULL) << PrettyMethod(method); 730e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom DCHECK_EQ(0U, method->GetGcMapLength()) << PrettyMethod(method); 7313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method); 7323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers bool first_occurrence; 7333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t invoke_stub_size = state->ComputeOatSize( 7343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurrence); 7353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first_occurrence) { 7363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->stats_.managed_to_native_code_bytes += invoke_stub_size; 7373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 738f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom const void* oat_code = state->GetOatCodeBegin(method); 7393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t code_size = state->ComputeOatSize(oat_code, &first_occurrence); 7403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first_occurrence) { 7413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->stats_.native_to_managed_code_bytes += code_size; 7423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 7433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (oat_code != method->GetCode()) { 7443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers StringAppendF(&summary, "\t\tOAT CODE: %p\n", oat_code); 7453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 7461984651929744dd603fd082e23eacd877b9bc177Ian Rogers } else if (method->IsAbstract() || method->IsCalleeSaveMethod() || 7471984651929744dd603fd082e23eacd877b9bc177Ian Rogers method->IsResolutionMethod()) { 748d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers DCHECK(method->GetGcMap() == NULL) << PrettyMethod(method); 749e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom DCHECK_EQ(0U, method->GetGcMapLength()) << PrettyMethod(method); 7503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK(method->GetMappingTable() == NULL) << PrettyMethod(method); 751916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom } else { 752e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom DCHECK(method->GetGcMap() != NULL) << PrettyMethod(method); 753e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom DCHECK_NE(0U, method->GetGcMapLength()) << PrettyMethod(method); 754916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 7556d4d9fcb4f01e287ee29e81cd1c941ee5d11d379Ian Rogers const DexFile::CodeItem* code_item = MethodHelper(method).GetCodeItem(); 756d81871cbbaa34c649e488f94f61a981db33123e5Ian Rogers size_t dex_instruction_bytes = code_item->insns_size_in_code_units_ * 2; 757916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom state->stats_.dex_instruction_bytes += dex_instruction_bytes; 758e7d856b911222aa000ca2be0f8f63f5b292141c3Brian Carlstrom 7593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers bool first_occurance; 7603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t gc_map_bytes = state->ComputeOatSize(method->GetGcMapRaw(), &first_occurance); 7613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first_occurance) { 7623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->stats_.gc_map_bytes += gc_map_bytes; 7633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 7643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 7653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t pc_mapping_table_bytes = 7663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->ComputeOatSize(method->GetMappingTableRaw(), &first_occurance); 7673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first_occurance) { 7683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->stats_.pc_mapping_table_bytes += pc_mapping_table_bytes; 7693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 7703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 7713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t vmap_table_bytes = 7723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->ComputeOatSize(method->GetVmapTableRaw(), &first_occurance); 7733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first_occurance) { 7743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->stats_.vmap_table_bytes += vmap_table_bytes; 7753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 7763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 7773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t invoke_stub_size = state->ComputeOatSize( 7783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers reinterpret_cast<const void*>(method->GetInvokeStub()), &first_occurance); 7793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first_occurance) { 7803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->stats_.native_to_managed_code_bytes += invoke_stub_size; 7813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 782f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom const void* oat_code_begin = state->GetOatCodeBegin(method); 783f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom const void* oat_code_end = state->GetOatCodeEnd(method); 784f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom // TODO: use oat_code_size and remove code_size based on offsets 785f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom // uint32_t oat_code_size = state->GetOatCodeSize(method); 786f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom size_t code_size = state->ComputeOatSize(oat_code_begin, &first_occurance); 7873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first_occurance) { 7883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->stats_.managed_code_bytes += code_size; 7893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 7903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->stats_.managed_code_bytes_ignoring_deduplication += code_size; 7913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 792f8bbb8448c733e9e3ad43aad69774c37888329b1Brian Carlstrom StringAppendF(&summary, "\t\tOAT CODE: %p-%p\n", oat_code_begin, oat_code_end); 793d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers StringAppendF(&summary, "\t\tSIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n", 7943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes); 7953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 7963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t total_size = dex_instruction_bytes + gc_map_bytes + pc_mapping_table_bytes + 7973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers vmap_table_bytes + invoke_stub_size + code_size + object_bytes; 7983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 7993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers double expansion = 8003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers static_cast<double>(code_size) / static_cast<double>(dex_instruction_bytes); 8013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers state->stats_.ComputeOutliers(total_size, expansion, method); 80278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 80378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 804d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers std::string descriptor(ClassHelper(obj_class).GetDescriptor()); 805d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers state->stats_.descriptor_to_bytes[descriptor] += object_bytes; 806d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers state->stats_.descriptor_to_count[descriptor] += 1; 807d5b32607798a46a905ba2d8d5bf7507cc970aa58Ian Rogers 80827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom state->os_ << summary << std::flush; 80978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 81027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom 8113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers std::set<const void*> already_seen_; 8123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers // Compute the size of the given data within the oat file and whether this is the first time 8133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers // this data has been requested 8143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t ComputeOatSize(const void* oat_data, bool* first_occurance) { 8153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (already_seen_.count(oat_data) == 0) { 8163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers *first_occurance = true; 8173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers already_seen_.insert(oat_data); 8183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } else { 8193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers *first_occurance = false; 8203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 8213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return oat_dumper_->ComputeSize(oat_data); 82227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 823916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 824916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom public: 825916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom struct Stats { 8263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t oat_file_bytes; 827916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t file_bytes; 828916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 829916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t header_bytes; 830916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t object_bytes; 831916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t alignment_bytes; 832916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 833916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t managed_code_bytes; 8343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t managed_code_bytes_ignoring_deduplication; 835916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t managed_to_native_code_bytes; 836916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t native_to_managed_code_bytes; 837916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 8383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t gc_map_bytes; 839916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t pc_mapping_table_bytes; 8403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t vmap_table_bytes; 841916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 842916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t dex_instruction_bytes; 843916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 8443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers std::vector<Method*> method_outlier; 8453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers std::vector<size_t> method_outlier_size; 8463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers std::vector<double> method_outlier_expansion; 8473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 8483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers explicit Stats() 8493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers : oat_file_bytes(0), 8503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers file_bytes(0), 851916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom header_bytes(0), 852916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom object_bytes(0), 853916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom alignment_bytes(0), 854916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom managed_code_bytes(0), 8553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers managed_code_bytes_ignoring_deduplication(0), 856916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom managed_to_native_code_bytes(0), 857916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom native_to_managed_code_bytes(0), 8583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers gc_map_bytes(0), 859916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom pc_mapping_table_bytes(0), 8603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers vmap_table_bytes(0), 861916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom dex_instruction_bytes(0) {} 862916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 863e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes typedef std::map<std::string, size_t> TableBytes; 864916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom TableBytes descriptor_to_bytes; 865916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 866e5448b5a12003b405b22cde3b94f962ab4888a87Elliott Hughes typedef std::map<std::string, size_t> TableCount; 867916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom TableCount descriptor_to_count; 868916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 8693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers double PercentOfOatBytes(size_t size) { 8703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers return (static_cast<double>(size) / static_cast<double>(oat_file_bytes)) * 100; 8713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 8723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 873916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom double PercentOfFileBytes(size_t size) { 874916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom return (static_cast<double>(size) / static_cast<double>(file_bytes)) * 100; 875916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom } 876916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 877916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom double PercentOfObjectBytes(size_t size) { 878916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom return (static_cast<double>(size) / static_cast<double>(object_bytes)) * 100; 879916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom } 880916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 8813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void ComputeOutliers(size_t total_size, double expansion, Method* method) { 8823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers method_outlier_size.push_back(total_size); 8833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers method_outlier_expansion.push_back(expansion); 8843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers method_outlier.push_back(method); 8853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 8863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 8873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers void DumpOutliers(std::ostream& os) { 8883a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t sum_of_sizes = 0; 8893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t sum_of_sizes_squared = 0; 8903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t sum_of_expansion = 0; 8913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t sum_of_expansion_squared = 0; 8923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t n = method_outlier_size.size(); 8933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t i = 0; i < n; i++) { 8943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t cur_size = method_outlier_size[i]; 8953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers sum_of_sizes += cur_size; 8963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers sum_of_sizes_squared += cur_size * cur_size; 8973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers double cur_expansion = method_outlier_expansion[i]; 8983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers sum_of_expansion += cur_expansion; 8993a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers sum_of_expansion_squared += cur_expansion * cur_expansion; 9003a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9013a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t size_mean = sum_of_sizes / n; 9023a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t size_variance = (sum_of_sizes_squared - sum_of_sizes * size_mean) / (n - 1); 9033a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers double expansion_mean = sum_of_expansion / n; 9043a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers double expansion_variance = 9053a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers (sum_of_expansion_squared - sum_of_expansion * expansion_mean) / (n - 1); 9063a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 9073a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers // Dump methods whose size is a certain number of standard deviations from the mean 9083a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t dumped_values = 0; 9093a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t skipped_values = 0; 9103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t i = 100; i > 0; i--) { // i is the current number of standard deviations 9113a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t cur_size_variance = i * i * size_variance; 9123a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers bool first = true; 9133a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t j = 0; j < n; j++) { 9143a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t cur_size = method_outlier_size[j]; 9153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (cur_size > size_mean) { 9163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t cur_var = cur_size - size_mean; 9173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers cur_var = cur_var * cur_var; 9183a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (cur_var > cur_size_variance) { 9193a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (dumped_values > 20) { 9203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (i == 1) { 9213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers skipped_values++; 9223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } else { 9233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers i = 2; // jump to counting for 1 standard deviation 9243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers break; 9253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } else { 9273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first) { 9283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "\nBig methods (size > " << i << " standard deviations the norm):" 9293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << std::endl; 9303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers first = false; 9313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "\t" << PrettyMethod(method_outlier[j]) << " requires storage of " 9333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << PrettySize(cur_size) << std::endl; 9343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers method_outlier_size[j] = 0; // don't consider this method again 9353a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers dumped_values++; 9363a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (skipped_values > 0) { 9423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "\t... skipped " << skipped_values 9433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << " methods with size > 1 standard deviation from the norm" << std::endl; 9443a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9453a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << std::endl << std::flush; 9463a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 9473a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers // Dump methods whose expansion is a certain number of standard deviations from the mean 9483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers dumped_values = 0; 9493a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers skipped_values = 0; 9503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t i = 10; i > 0; i--) { // i is the current number of standard deviations 9513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers double cur_expansion_variance = i * i * expansion_variance; 9523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers bool first = true; 9533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers for (size_t j = 0; j < n; j++) { 9543a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers double cur_expansion = method_outlier_expansion[j]; 9553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (cur_expansion > expansion_mean) { 9563a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers size_t cur_var = cur_expansion - expansion_mean; 9573a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers cur_var = cur_var * cur_var; 9583a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (cur_var > cur_expansion_variance) { 9593a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (dumped_values > 20) { 9603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (i == 1) { 9613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers skipped_values++; 9623a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } else { 9633a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers i = 2; // jump to counting for 1 standard deviation 9643a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers break; 9653a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9663a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } else { 9673a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (first) { 9683a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "\nLarge expansion methods (size > " << i 9693a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << " standard deviations the norm):" << std::endl; 9703a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers first = false; 9713a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9723a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "\t" << PrettyMethod(method_outlier[j]) << " expanded code by " 9733a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << cur_expansion << std::endl; 9743a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers method_outlier_expansion[j] = 0.0; // don't consider this method again 9753a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers dumped_values++; 9763a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9773a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9783a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9793a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9803a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9813a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers if (skipped_values > 0) { 9823a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "\t... skipped " << skipped_values 9833a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << " methods with expansion > 1 standard deviation from the norm" << std::endl; 9843a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9853a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << std::endl << std::flush; 9863a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers } 9873a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 988916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom void Dump(std::ostream& os) { 9893a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << "\tart_file_bytes = " << PrettySize(file_bytes) << std::endl << std::endl 9903a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << "\tart_file_bytes = header_bytes + object_bytes + alignment_bytes" << std::endl 9913a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << StringPrintf("\theader_bytes = %8zd (%2.0f%% of art file bytes)\n" 9923a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers "\tobject_bytes = %8zd (%2.0f%% of art file bytes)\n" 9933a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers "\talignment_bytes = %8zd (%2.0f%% of art file bytes)\n", 9943a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers header_bytes, PercentOfFileBytes(header_bytes), 9953a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers object_bytes, PercentOfFileBytes(object_bytes), 9963a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers alignment_bytes, PercentOfFileBytes(alignment_bytes)) 9973a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << std::endl << std::flush; 9983a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 999916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom CHECK_EQ(file_bytes, header_bytes + object_bytes + alignment_bytes); 1000916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 1001916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom os << "\tobject_bytes = sum of descriptor_to_bytes values below:\n"; 1002916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t object_bytes_total = 0; 1003916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom typedef TableBytes::const_iterator It; // TODO: C++0x auto 1004916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom for (It it = descriptor_to_bytes.begin(), end = descriptor_to_bytes.end(); it != end; ++it) { 1005955724179c6c739524f610023287f56b24dc31deElliott Hughes const std::string& descriptor(it->first); 1006916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t bytes = it->second; 1007916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom size_t count = descriptor_to_count[descriptor]; 1008916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom double average = static_cast<double>(bytes) / static_cast<double>(count); 1009916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom double percent = PercentOfObjectBytes(bytes); 1010ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes os << StringPrintf("\t%32s %8zd bytes %6zd instances " 1011916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom "(%3.0f bytes/instance) %2.0f%% of object_bytes\n", 1012916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom descriptor.c_str(), bytes, count, 1013916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom average, percent); 1014916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 1015916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom object_bytes_total += bytes; 1016916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom } 10173a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << std::endl << std::flush; 1018916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom CHECK_EQ(object_bytes, object_bytes_total); 1019916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 10203a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << StringPrintf("\tmanaged_code_bytes = %8zd (%2.0f%% of oat file bytes)\n" 10213a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers "\tmanaged_to_native_code_bytes = %8zd (%2.0f%% of oat file bytes)\n" 10223a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers "\tnative_to_managed_code_bytes = %8zd (%2.0f%% of oat file bytes)\n", 10233a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers managed_code_bytes, PercentOfOatBytes(managed_code_bytes), 10243a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers managed_to_native_code_bytes, PercentOfOatBytes(managed_to_native_code_bytes), 10253a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers native_to_managed_code_bytes, PercentOfOatBytes(native_to_managed_code_bytes)) 10263a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << std::endl << std::flush; 10273a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 10283a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << StringPrintf("\tgc_map_bytes = %7zd (%2.0f%% of oat file_bytes)\n" 10293a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers "\tpc_mapping_table_bytes = %7zd (%2.0f%% of oat file_bytes)\n" 10303a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers "\tvmap_table_bytes = %7zd (%2.0f%% of oat file_bytes)\n", 10313a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers gc_map_bytes, PercentOfOatBytes(gc_map_bytes), 10323a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers pc_mapping_table_bytes, PercentOfOatBytes(pc_mapping_table_bytes), 10333a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers vmap_table_bytes, PercentOfOatBytes(vmap_table_bytes)) 10343a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers << std::endl << std::flush; 1035916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 1036ad6c9c3dbf7541340f22ccbb333f08556ad7e000Elliott Hughes os << StringPrintf("\tdex_instruction_bytes = %zd\n", dex_instruction_bytes); 10373a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << StringPrintf("\tmanaged_code_bytes expansion = %.2f (ignoring deduplication %.2f)\n", 10383a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers static_cast<double>(managed_code_bytes) / static_cast<double>(dex_instruction_bytes), 10393a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers static_cast<double>(managed_code_bytes_ignoring_deduplication) / 10403a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers static_cast<double>(dex_instruction_bytes)); 10413a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers os << std::endl << std::flush; 10423a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers 10433a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DumpOutliers(os); 1044916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom } 1045916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom } stats_; 1046916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom 1047916e74e45b60902af342a71bdbfb806ff29c6c2bBrian Carlstrom private: 10483a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers UniquePtr<OatDumper> oat_dumper_; 104927ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom std::ostream& os_; 10503a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const std::string image_filename_; 10513a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const std::string host_prefix_; 10523a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers Space& image_space_; 10533a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers const ImageHeader& image_header_; 1054d1bb4f6b7c8dda429f61937cd42f3a0b7367c271Elliott Hughes 10553a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers DISALLOW_COPY_AND_ASSIGN(ImageDumper); 105678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom}; 105778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 105878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint oatdump(int argc, char** argv) { 105978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom // Skip over argv[0]. 106078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom argv++; 106178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom argc--; 106278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 106378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom if (argc == 0) { 1064aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom fprintf(stderr, "No arguments specified\n"); 106578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom usage(); 106678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 106778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 1068aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom const char* oat_filename = NULL; 106978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom const char* image_filename = NULL; 107078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom const char* boot_image_filename = NULL; 107158ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom std::string host_prefix; 107227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom std::ostream* os = &std::cout; 107327ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom UniquePtr<std::ofstream> out; 107478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 107578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom for (int i = 0; i < argc; i++) { 107678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom const StringPiece option(argv[i]); 1077a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom if (option.starts_with("--oat-file=")) { 1078a6cc893c4b142cd410fc956963b6f5a014e983adBrian Carlstrom oat_filename = option.substr(strlen("--oat-file=")).data(); 1079aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } else if (option.starts_with("--image=")) { 108078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom image_filename = option.substr(strlen("--image=")).data(); 1081e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } else if (option.starts_with("--boot-image=")) { 1082e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom boot_image_filename = option.substr(strlen("--boot-image=")).data(); 108358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom } else if (option.starts_with("--host-prefix=")) { 108458ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom host_prefix = option.substr(strlen("--host-prefix=")).data(); 108527ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } else if (option.starts_with("--output=")) { 108627ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom const char* filename = option.substr(strlen("--output=")).data(); 108727ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom out.reset(new std::ofstream(filename)); 108827ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom if (!out->good()) { 1089aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom fprintf(stderr, "Failed to open output filename %s\n", filename); 109027ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom usage(); 109127ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom } 109227ec961a1da540ba7f16c07a682585ab167317adBrian Carlstrom os = out.get(); 109378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } else { 1094aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom fprintf(stderr, "Unknown argument %s\n", option.data()); 109578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom usage(); 109678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 109778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 109878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 1099aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom if (image_filename == NULL && oat_filename == NULL) { 1100362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes fprintf(stderr, "Either --image or --oat must be specified\n"); 1101362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes return EXIT_FAILURE; 110278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 110378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 1104aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom if (image_filename != NULL && oat_filename != NULL) { 1105362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes fprintf(stderr, "Either --image or --oat must be specified but not both\n"); 1106362f9bc807169bcfc8761dde067bbfb79b5ad0fdElliott Hughes return EXIT_FAILURE; 1107aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 1108aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 1109aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom if (oat_filename != NULL) { 11103a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, NULL); 1111aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom if (oat_file == NULL) { 1112aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom fprintf(stderr, "Failed to open oat file from %s\n", oat_filename); 1113aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom return EXIT_FAILURE; 1114aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 11153a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers OatDumper oat_dumper(*oat_file); 11163a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers oat_dumper.Dump(*os); 1117aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom return EXIT_SUCCESS; 1118aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 1119aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom 112078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom Runtime::Options options; 112178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom std::string image_option; 1122e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom std::string oat_option; 112378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom std::string boot_image_option; 1124e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom std::string boot_oat_option; 112558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom if (boot_image_filename != NULL) { 112658ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom boot_image_option += "-Ximage:"; 112758ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom boot_image_option += boot_image_filename; 112858ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom options.push_back(std::make_pair(boot_image_option.c_str(), reinterpret_cast<void*>(NULL))); 112958ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom } 1130aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom if (image_filename != NULL) { 1131aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom image_option += "-Ximage:"; 1132aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom image_option += image_filename; 1133aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL))); 1134aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom } 113558ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom 1136fe487d0c789b94e75c93a2b799f1955c3e4edb10Brian Carlstrom if (host_prefix.empty()) { 1137fe487d0c789b94e75c93a2b799f1955c3e4edb10Brian Carlstrom const char* android_product_out = getenv("ANDROID_PRODUCT_OUT"); 1138fe487d0c789b94e75c93a2b799f1955c3e4edb10Brian Carlstrom if (android_product_out != NULL) { 1139fe487d0c789b94e75c93a2b799f1955c3e4edb10Brian Carlstrom host_prefix = android_product_out; 1140fe487d0c789b94e75c93a2b799f1955c3e4edb10Brian Carlstrom } 1141fe487d0c789b94e75c93a2b799f1955c3e4edb10Brian Carlstrom } 114258ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom if (!host_prefix.empty()) { 114358ae9416e197ae68ed12ed43d87407d4dfb15093Brian Carlstrom options.push_back(std::make_pair("host-prefix", host_prefix.c_str())); 114478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 114578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 114678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom UniquePtr<Runtime> runtime(Runtime::Create(options, false)); 114778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom if (runtime.get() == NULL) { 1148aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom fprintf(stderr, "Failed to create runtime\n"); 114978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom return EXIT_FAILURE; 115078128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 115178128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 1152b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes Heap* heap = Runtime::Current()->GetHeap(); 1153b3bd5f07884f5a1f2b84224363b1372d7c28d447Elliott Hughes ImageSpace* image_space = heap->GetSpaces()[heap->GetSpaces().size()-2]->AsImageSpace(); 115478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom CHECK(image_space != NULL); 115578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom const ImageHeader& image_header = image_space->GetImageHeader(); 115678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom if (!image_header.IsValid()) { 1157aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom fprintf(stderr, "Invalid image header %s\n", image_filename); 115878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom return EXIT_FAILURE; 115978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom } 11603a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers ImageDumper image_dumper(*os, image_filename, host_prefix, *image_space, image_header); 11613a5c1ce3f11805a3382046f699c8fb1410a602b3Ian Rogers image_dumper.Dump(); 116278128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom return EXIT_SUCCESS; 116378128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom} 116478128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 116578128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom} // namespace art 116678128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom 116778128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstromint main(int argc, char** argv) { 116878128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom return art::oatdump(argc, argv); 116978128a63b2615744760b7f8ab83df9764a5d4a95Brian Carlstrom} 1170