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