oat_writer.cc revision 387b699e3dc55309023ae2427a76a1ca1d51b0cd
1e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom// Copyright 2011 Google Inc. All Rights Reserved. 2e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 3e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "oat_writer.h" 4e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 5e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "class_linker.h" 6e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "class_loader.h" 7e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "file.h" 8e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "os.h" 9e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom#include "stl_util.h" 10e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 11e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromnamespace art { 12e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 133320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrombool OatWriter::Create(const std::string& filename, 143320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const ClassLoader* class_loader, 153320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const Compiler& compiler) { 16aded5f7ab991f3c1132851599d3bc60ff6707eedBrian Carlstrom const std::vector<const DexFile*>& dex_files = ClassLoader::GetCompileTimeClassPath(class_loader); 173320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom OatWriter oat_writer(dex_files, class_loader, compiler); 18e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return oat_writer.Write(filename); 19e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 20e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 213320cf46afd082398aa401b246e6f301cebdf64dBrian CarlstromOatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, 223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const ClassLoader* class_loader, 233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const Compiler& compiler) { 243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom compiler_ = &compiler; 25e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_loader_ = class_loader; 26e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_files_ = &dex_files; 27e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 28e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t offset = InitOatHeader(); 29e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatDexFiles(offset); 30e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatClasses(offset); 31e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatMethods(offset); 32e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCode(offset); 33e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeDexFiles(offset); 34e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 35e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK_EQ(dex_files_->size(), oat_dex_files_.size()); 36e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK_EQ(dex_files_->size(), oat_classes_.size()); 37e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 38e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 39e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatHeader() { 40e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatHeader 41e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header_ = new OatHeader(dex_files_); 42e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t offset = sizeof(*oat_header_); 43e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 44e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 45e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 46e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatDexFiles(size_t offset) { 47e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatDexFiles 48e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 49e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 50e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 51e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom OatDexFile* oat_dex_file = new OatDexFile(*dex_file); 52e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_dex_files_.push_back(oat_dex_file); 53e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset += oat_dex_file->SizeOf(); 54e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 55e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 56e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 57e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 58e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatClasses(size_t offset) { 59e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatClasses 60e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // calculate the offsets within OatDexFiles to OatClasses 61e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 62e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // set offset in OatDexFile to OatClasses 63e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_dex_files_[i]->classes_offset_ = offset; 64e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_dex_files_[i]->UpdateChecksum(*oat_header_); 65e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 66e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 67e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom OatClasses* oat_classes = new OatClasses(*dex_file); 68e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_classes_.push_back(oat_classes); 69e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset += oat_classes->SizeOf(); 70e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 71e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 72e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 73e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 74e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatMethods(size_t offset) { 75e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // create the OatMethods 76e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // calculate the offsets within OatClasses to OatMethods 77e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t class_index = 0; 78e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 79e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 80e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t class_def_index = 0; 81e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index < dex_file->NumClassDefs(); 82e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index++, class_index++) { 83e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_classes_[i]->methods_offsets_[class_def_index] = offset; 84e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); 85e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file->GetClassData(class_def); 86e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom DexFile::ClassDataHeader header = dex_file->ReadClassDataHeader(&class_data); 87e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t num_direct_methods = header.direct_methods_size_; 88e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t num_virtual_methods = header.virtual_methods_size_; 89e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom uint32_t num_methods = num_direct_methods + num_virtual_methods; 90e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom OatMethods* oat_methods = new OatMethods(num_methods); 91e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_methods_.push_back(oat_methods); 92e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset += oat_methods->SizeOf(); 93e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 94e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_classes_[i]->UpdateChecksum(*oat_header_); 95e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 96e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 97e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 98e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 99e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCode(size_t offset) { 100e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // calculate the offsets within OatHeader to executable code 101e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t old_offset = offset; 102e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // required to be on a new page boundary 103e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = RoundUp(offset, kPageSize); 104e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header_->SetExecutableOffset(offset); 105e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom executable_offset_padding_length_ = offset - old_offset; 106e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 107e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 108e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 109e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeDexFiles(size_t offset) { 110e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // calculate the offsets within OatMethods 111e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t oat_class_index = 0; 112e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != dex_files_->size(); ++i) { 113e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 114e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 115e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeDexFile(offset, oat_class_index, *dex_file); 116e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 117e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 118e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 119e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 120e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeDexFile(size_t offset, 121e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t& oat_class_index, 122e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file) { 123e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t class_def_index = 0; 124e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index < dex_file.NumClassDefs(); 125e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index++, oat_class_index++) { 126e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); 127e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeClassDef(offset, oat_class_index, dex_file, class_def); 128e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_methods_[oat_class_index]->UpdateChecksum(*oat_header_); 129e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 130e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 131e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 132e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 133e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeClassDef(size_t offset, 134e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t oat_class_index, 135e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file, 136e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def) { 137e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file.GetClassData(class_def); 138e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data); 139e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t num_virtual_methods = header.virtual_methods_size_; 140e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const char* descriptor = dex_file.GetClassDescriptor(class_def); 141e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 142e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // TODO: remove code ByteArrays from Class/Method (and therefore ClassLoader) 143e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // TODO: don't write code for shared stubs 144e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, class_loader_); 145387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers if (klass == NULL) { 146387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation(); 147387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers Thread* thread = Thread::Current(); 148387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers DCHECK(thread->IsExceptionPending()); 149387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers thread->ClearException(); 150387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers return offset; 151387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers } 152e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK_EQ(klass->GetClassLoader(), class_loader_); 153e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK_EQ(oat_methods_[oat_class_index]->method_offsets_.size(), 154e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom klass->NumDirectMethods() + num_virtual_methods); 155e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t class_def_method_index = 0; 156e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i < klass->NumDirectMethods(); i++, class_def_method_index++) { 157e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom Method* method = klass->GetDirectMethod(i); 158e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(method != NULL) << descriptor << " direct " << i; 159e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method); 160e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 161e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods 162e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i < num_virtual_methods; i++, class_def_method_index++) { 163e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom Method* method = klass->GetVirtualMethod(i); 164e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(method != NULL) << descriptor << " virtual " << i; 165e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method); 166e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 167e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 168e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 169e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 170e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::InitOatCodeMethod(size_t offset, 171e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t oat_class_index, 172e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t class_def_method_index, 173e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom Method* method) { 1743320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // derived from CompiledMethod if available 1753320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t code_offset = 0; 1763320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t frame_size_in_bytes = kStackAlignment; 1773320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t return_pc_offset_in_bytes = 0; 1783320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t core_spill_mask = 0; 1793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t fp_spill_mask = 0; 1803320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t mapping_table_offset = 0; 1813320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t vmap_table_offset = 0; 1823320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // derived from CompiledInvokeStub if available 1833320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t invoke_stub_offset = 0; 1843320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 1853320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method); 1863320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 1873320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset = compiled_method->AlignCode(offset); 18806b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(offset, kArmAlignment); 1893320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& code = compiled_method->GetCode(); 1903320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t code_size = code.size() * sizeof(code[0]); 1913320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t thumb_offset = compiled_method->CodeDelta(); 1923320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset = (code_size == 0) ? 0 : offset + thumb_offset; 1933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += code_size; 1943320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&code[0], code_size); 1953320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 1963320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 1973320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return_pc_offset_in_bytes = compiled_method->GetReturnPcOffsetInBytes(); 1983320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom core_spill_mask = compiled_method->GetCoreSpillMask(); 1993320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom fp_spill_mask = compiled_method->GetFpSpillMask(); 200e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 2013320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2023320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(frame_size_in_bytes); 2033320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&frame_size_in_bytes, sizeof(frame_size_in_bytes)); 2043320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2053320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(return_pc_offset_in_bytes); 2063320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes)); 2073320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2083320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(core_spill_mask); 2093320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&core_spill_mask, sizeof(core_spill_mask)); 2103320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2113320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += sizeof(fp_spill_mask); 2123320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&fp_spill_mask, sizeof(fp_spill_mask)); 2133320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2143320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 2153320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); 2163320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 2173320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom mapping_table_offset = (mapping_table_size == 0) ? 0 : offset; 2183320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += mapping_table_size; 2193320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size); 2203320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2213320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); 2223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 2233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom vmap_table_offset = (vmap_table_size == 0) ? 0 : offset; 2243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += vmap_table_size; 2253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size); 2263320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 2273320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2283320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method); 2293320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_invoke_stub != NULL) { 2303320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet()); 23106b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(offset, kArmAlignment); 2323320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 2333320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); 2343320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom invoke_stub_offset = (invoke_stub_size == 0) ? 0 : offset; 2353320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom offset += invoke_stub_size; 2363320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size); 2373320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 2383320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2393320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom oat_methods_[oat_class_index]->method_offsets_[class_def_method_index] 2403320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom = OatMethodOffsets(code_offset, 2413320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom frame_size_in_bytes, 2423320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return_pc_offset_in_bytes, 2433320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom core_spill_mask, 2443320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom fp_spill_mask, 2453320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom mapping_table_offset, 2463320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom vmap_table_offset, 2473320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom invoke_stub_offset); 2483320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 2493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom // Note that we leave the offset and values back in the Method where ImageWriter will find them 2503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom method->SetOatCodeOffset(code_offset); 2513320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom method->SetFrameSizeInBytes(frame_size_in_bytes); 2523320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom method->SetCoreSpillMask(core_spill_mask); 2533320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom method->SetFpSpillMask(fp_spill_mask); 2543320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom method->SetOatMappingTableOffset(mapping_table_offset); 2553320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom method->SetOatVmapTableOffset(vmap_table_offset); 2563320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom method->SetOatInvokeStubOffset(invoke_stub_offset); 2573320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 258e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return offset; 259e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 260e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 2613320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom#define DCHECK_CODE_OFFSET() \ 2623320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_EQ(static_cast<off_t>(code_offset), lseek(file->Fd(), 0, SEEK_CUR)) 2633320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 264e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatWriter::Write(const std::string& filename) { 265e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom UniquePtr<File> file(OS::OpenFile(filename.c_str(), true)); 266e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (file.get() == NULL) { 267e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 268e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 269e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 270e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(oat_header_, sizeof(*oat_header_))) { 271e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write oat header to " << filename; 272e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 273e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 274e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 275e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!WriteTables(file.get())) { 276e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom LOG(ERROR) << "Failed to write oat tables to " << filename; 277e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 278e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 279e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 280e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t code_offset = WriteCode(file.get()); 281e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 282e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom LOG(ERROR) << "Failed to write oat code to " << filename; 283e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 284e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 285e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 286e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom code_offset = WriteCodeDexFiles(file.get(), code_offset); 287e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 288e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom LOG(ERROR) << "Failed to write oat code for dex files to " << filename; 289e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 290e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 291e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 292e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 293e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 294e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 295e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatWriter::WriteTables(File* file) { 296e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 297e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!oat_dex_files_[i]->Write(file)) { 298e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write oat dex information"; 299e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 300e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 301e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 302e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != oat_classes_.size(); ++i) { 303e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!oat_classes_[i]->Write(file)) { 304e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write oat classes information"; 305e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 306e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 307e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 308e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != oat_methods_.size(); ++i) { 309e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!oat_methods_[i]->Write(file)) { 310e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write oat methods information"; 311e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 312e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 313e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 314e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 315e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 316e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 317e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCode(File* file) { 318e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom uint32_t code_offset = oat_header_->GetExecutableOffset(); 319e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom off_t new_offset = lseek(file->Fd(), executable_offset_padding_length_, SEEK_CUR); 320e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (static_cast<uint32_t>(new_offset) != code_offset) { 3213320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset 3223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom << " Expected: " << code_offset; 323e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 324e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 3253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 326e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 327e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 328e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 329e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) { 330e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i != oat_classes_.size(); ++i) { 331e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile* dex_file = (*dex_files_)[i]; 332e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom CHECK(dex_file != NULL); 333e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom code_offset = WriteCodeDexFile(file, code_offset, *dex_file); 334e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 335e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 336e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 337e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 338e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 339e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 340e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 341e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCodeDexFile(File* file, 342e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t code_offset, 343e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file) { 344e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t class_def_index = 0; 345e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index < dex_file.NumClassDefs(); 346e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom class_def_index++) { 347e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); 348e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom code_offset = WriteCodeClassDef(file, code_offset, dex_file, class_def); 349e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 350e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 351e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 352e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 353e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 354e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 355e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 356e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::WriteCodeClassDef(File* file, 357e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t code_offset, 358e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile& dex_file, 359e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const DexFile::ClassDef& class_def) { 360e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const byte* class_data = dex_file.GetClassData(class_def); 361e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data); 362e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom size_t num_virtual_methods = header.virtual_methods_size_; 363e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const char* descriptor = dex_file.GetClassDescriptor(class_def); 3643320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 365e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom Class* klass = class_linker->FindClass(descriptor, class_loader_); 366387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers if (klass == NULL) { 367387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation(); 368387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers Thread* thread = Thread::Current(); 369387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers DCHECK(thread->IsExceptionPending()); 370387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers thread->ClearException(); 371387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers return code_offset; 372387b699e3dc55309023ae2427a76a1ca1d51b0cdIan Rogers } 373e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 374e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // TODO: deduplicate code arrays 375e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // Note that we clear the code array here, image_writer will use GetCodeOffset to find it 376e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i < klass->NumDirectMethods(); i++) { 377e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom Method* method = klass->GetDirectMethod(i); 378e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom code_offset = WriteCodeMethod(file, code_offset, method); 379e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 380e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 381e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 382e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 383e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods 384e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = 0; i < num_virtual_methods; i++) { 385e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom Method* method = klass->GetVirtualMethod(i); 386e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom code_offset = WriteCodeMethod(file, code_offset, method); 387e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (code_offset == 0) { 388e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return 0; 389e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 390e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 391e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom for (size_t i = num_virtual_methods; i < klass->NumVirtualMethods(); i++) { 392e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom Method* method = klass->GetVirtualMethod(i); 3933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom CHECK(compiler_->GetCompiledMethod(method) == NULL) << PrettyMethod(method); 394e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 395e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 396e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 397e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 398f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughessize_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, Method* method) { 3993320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method); 4003320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 4013320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset); 402e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom uint32_t aligned_code_delta = aligned_code_offset - code_offset; 403e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (aligned_code_delta != 0) { 404e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); 405e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { 4063320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset 4073320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom << " Expected: " << aligned_code_offset; 408e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 409e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 410e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom code_offset += aligned_code_delta; 4113320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 412e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 41306b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(code_offset, kArmAlignment); 4143320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& code = compiled_method->GetCode(); 4153320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t code_size = code.size() * sizeof(code[0]); 4163320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK((code_size == 0 && method->GetOatCodeOffset() == 0) 4173320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom || code_offset + compiled_method->CodeDelta() == method->GetOatCodeOffset()); 4183320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&code[0], code_size)) { 419e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write method code for " << PrettyMethod(method); 420e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 421e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 4223320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += code_size; 4233320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 4243320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4253320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4263320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t frame_size_in_bytes = method->GetFrameSizeInBytes(); 4273320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t return_pc_offset_in_bytes = method->GetReturnPcOffsetInBytes(); 4283320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t core_spill_mask = method->GetCoreSpillMask(); 4293320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t fp_spill_mask = method->GetFpSpillMask(); 4303320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&frame_size_in_bytes, sizeof(frame_size_in_bytes))) { 4313320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to write method frame size for " << PrettyMethod(method); 4323320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 4333320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4343320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(frame_size_in_bytes); 4353320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes))) { 4363320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to write method return pc offset for " << PrettyMethod(method); 4373320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 4383320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4393320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(return_pc_offset_in_bytes); 4403320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&core_spill_mask, sizeof(core_spill_mask))) { 4413320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to write method core spill mask for " << PrettyMethod(method); 4423320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 4433320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4443320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(core_spill_mask); 4453320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&fp_spill_mask, sizeof(fp_spill_mask))) { 4463320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to write method fp spill mask for " << PrettyMethod(method); 4473320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 4483320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4493320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += sizeof(fp_spill_mask); 4503320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4513320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_method != NULL) { 4523320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); 4533320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 4543320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK((mapping_table_size == 0 && method->GetOatMappingTableOffset() == 0) 4553320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom || code_offset == method->GetOatMappingTableOffset()); 4563320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&mapping_table[0], mapping_table_size)) { 4573320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to write mapping table for " << PrettyMethod(method); 4583320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 4593320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4603320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += mapping_table_size; 4613320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 4623320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4633320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); 4643320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 4653320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK((vmap_table_size == 0 && method->GetOatVmapTableOffset() == 0) 4663320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom || code_offset == method->GetOatVmapTableOffset()); 4673320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&vmap_table[0], vmap_table_size)) { 4683320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to write vmap table for " << PrettyMethod(method); 4693320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 4703320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4713320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += vmap_table_size; 4723320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 473e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 4743320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 4753320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method); 4763320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (compiled_invoke_stub != NULL) { 4773320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset, 4783320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom compiler_->GetInstructionSet()); 4793320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom uint32_t aligned_code_delta = aligned_code_offset - code_offset; 4803320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (aligned_code_delta != 0) { 4813320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); 4823320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { 4833320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset 4843320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom << " Expected: " << aligned_code_offset; 4853320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 4863320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4873320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += aligned_code_delta; 4883320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 4893320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 49006b37d91bb3d543002b1aee9829691f5e8bebc7eElliott Hughes DCHECK_ALIGNED(code_offset, kArmAlignment); 4913320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 4923320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); 4933320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK((invoke_stub_size == 0 && method->GetOatInvokeStubOffset() == 0) 494f09afe8fbd78943df6a8b10f03c36dcd190dd054Elliott Hughes || code_offset == method->GetOatInvokeStubOffset()) << PrettyMethod(method); 4953320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) { 4963320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom PLOG(ERROR) << "Failed to write invoke stub code for " << PrettyMethod(method); 4973320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom return false; 4983320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 4993320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom code_offset += invoke_stub_size; 5003320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom DCHECK_CODE_OFFSET(); 5013320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom } 5023320cf46afd082398aa401b246e6f301cebdf64dBrian Carlstrom 503e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return code_offset; 504e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 505e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 506e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatWriter::~OatWriter() { 507e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom delete oat_header_; 508e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom STLDeleteElements(&oat_dex_files_); 509e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom STLDeleteElements(&oat_classes_); 510e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom STLDeleteElements(&oat_methods_); 511e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 512e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 513e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) { 514e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom const std::string& location = dex_file.GetLocation(); 515e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_size_ = location.size(); 516e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data()); 517e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom dex_file_checksum_ = dex_file.GetHeader().checksum_; 518e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 519e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 520e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::OatDexFile::SizeOf() const { 521e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return sizeof(dex_file_location_size_) 522e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom + dex_file_location_size_ 523e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom + sizeof(dex_file_checksum_) 524e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom + sizeof(classes_offset_); 525e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 526e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 527e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid OatWriter::OatDexFile::UpdateChecksum(OatHeader& oat_header) const { 528e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_)); 529e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(dex_file_location_data_, dex_file_location_size_); 530e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(&dex_file_checksum_, sizeof(dex_file_checksum_)); 531e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(&classes_offset_, sizeof(classes_offset_)); 532e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 533e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 534e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatWriter::OatDexFile::Write(File* file) const { 535e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) { 536e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write dex file location length"; 537e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 538e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 539e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(dex_file_location_data_, dex_file_location_size_)) { 540e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write dex file location data"; 541e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 542e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 543e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(&dex_file_checksum_, sizeof(dex_file_checksum_))) { 544e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write dex file checksum"; 545e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 546e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 547e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(&classes_offset_, sizeof(classes_offset_))) { 548e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to write classes offset"; 549e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 550e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 551e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 552e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 553e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 554e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatWriter::OatClasses::OatClasses(const DexFile& dex_file) { 555e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom methods_offsets_.resize(dex_file.NumClassDefs()); 556e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 557e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 558e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::OatClasses::SizeOf() const { 559e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return (sizeof(methods_offsets_[0]) * methods_offsets_.size()); 560e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 561e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 562e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid OatWriter::OatClasses::UpdateChecksum(OatHeader& oat_header) const { 563e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(&methods_offsets_[0], SizeOf()); 564e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 565e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 566e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatWriter::OatClasses::Write(File* file) const { 567e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(&methods_offsets_[0], SizeOf())) { 568e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to methods offsets"; 569e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 570e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 571e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 572e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 573e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 574e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian CarlstromOatWriter::OatMethods::OatMethods(uint32_t methods_count) { 575e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom method_offsets_.resize(methods_count); 576e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 577e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 578e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromsize_t OatWriter::OatMethods::SizeOf() const { 579e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return (sizeof(method_offsets_[0]) * method_offsets_.size()); 580e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 581e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 582e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstromvoid OatWriter::OatMethods::UpdateChecksum(OatHeader& oat_header) const { 583e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom oat_header.UpdateChecksum(&method_offsets_[0], SizeOf()); 584e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 585e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 586e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrombool OatWriter::OatMethods::Write(File* file) const { 587e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom if (!file->WriteFully(&method_offsets_[0], SizeOf())) { 588e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom PLOG(ERROR) << "Failed to method offsets"; 589e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return false; 590e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom } 591e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom return true; 592e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} 593e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom 594e24fa61603a60ade3797e4a0c8b3fccb346cb048Brian Carlstrom} // namespace art 595