blob: 931dbc1597fb7f2b40a93f55155bd438e6caa23d [file] [log] [blame]
Brian Carlstrome24fa612011-09-29 00:53:55 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include "oat_writer.h"
4
5#include "class_linker.h"
6#include "class_loader.h"
7#include "file.h"
8#include "os.h"
9#include "stl_util.h"
10
11namespace art {
12
Brian Carlstrom3320cf42011-10-04 14:58:28 -070013bool OatWriter::Create(const std::string& filename,
14 const ClassLoader* class_loader,
15 const Compiler& compiler) {
Brian Carlstromaded5f72011-10-07 17:15:04 -070016 const std::vector<const DexFile*>& dex_files = ClassLoader::GetCompileTimeClassPath(class_loader);
Brian Carlstrom3320cf42011-10-04 14:58:28 -070017 OatWriter oat_writer(dex_files, class_loader, compiler);
Brian Carlstrome24fa612011-09-29 00:53:55 -070018 return oat_writer.Write(filename);
19}
20
Brian Carlstrom3320cf42011-10-04 14:58:28 -070021OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
22 const ClassLoader* class_loader,
23 const Compiler& compiler) {
24 compiler_ = &compiler;
Brian Carlstrome24fa612011-09-29 00:53:55 -070025 class_loader_ = class_loader;
26 dex_files_ = &dex_files;
27
28 size_t offset = InitOatHeader();
29 offset = InitOatDexFiles(offset);
30 offset = InitOatClasses(offset);
31 offset = InitOatMethods(offset);
32 offset = InitOatCode(offset);
33 offset = InitOatCodeDexFiles(offset);
34
35 CHECK_EQ(dex_files_->size(), oat_dex_files_.size());
36 CHECK_EQ(dex_files_->size(), oat_classes_.size());
37}
38
39size_t OatWriter::InitOatHeader() {
40 // create the OatHeader
41 oat_header_ = new OatHeader(dex_files_);
42 size_t offset = sizeof(*oat_header_);
43 return offset;
44}
45
46size_t OatWriter::InitOatDexFiles(size_t offset) {
47 // create the OatDexFiles
48 for (size_t i = 0; i != dex_files_->size(); ++i) {
49 const DexFile* dex_file = (*dex_files_)[i];
50 CHECK(dex_file != NULL);
51 OatDexFile* oat_dex_file = new OatDexFile(*dex_file);
52 oat_dex_files_.push_back(oat_dex_file);
53 offset += oat_dex_file->SizeOf();
54 }
55 return offset;
56}
57
58size_t OatWriter::InitOatClasses(size_t offset) {
59 // create the OatClasses
60 // calculate the offsets within OatDexFiles to OatClasses
61 for (size_t i = 0; i != dex_files_->size(); ++i) {
62 // set offset in OatDexFile to OatClasses
63 oat_dex_files_[i]->classes_offset_ = offset;
64 oat_dex_files_[i]->UpdateChecksum(*oat_header_);
65
66 const DexFile* dex_file = (*dex_files_)[i];
67 OatClasses* oat_classes = new OatClasses(*dex_file);
68 oat_classes_.push_back(oat_classes);
69 offset += oat_classes->SizeOf();
70 }
71 return offset;
72}
73
74size_t OatWriter::InitOatMethods(size_t offset) {
75 // create the OatMethods
76 // calculate the offsets within OatClasses to OatMethods
77 size_t class_index = 0;
78 for (size_t i = 0; i != dex_files_->size(); ++i) {
79 const DexFile* dex_file = (*dex_files_)[i];
80 for (size_t class_def_index = 0;
81 class_def_index < dex_file->NumClassDefs();
82 class_def_index++, class_index++) {
83 oat_classes_[i]->methods_offsets_[class_def_index] = offset;
84 const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
85 const byte* class_data = dex_file->GetClassData(class_def);
86 DexFile::ClassDataHeader header = dex_file->ReadClassDataHeader(&class_data);
87 size_t num_direct_methods = header.direct_methods_size_;
88 size_t num_virtual_methods = header.virtual_methods_size_;
89 uint32_t num_methods = num_direct_methods + num_virtual_methods;
90 OatMethods* oat_methods = new OatMethods(num_methods);
91 oat_methods_.push_back(oat_methods);
92 offset += oat_methods->SizeOf();
93 }
94 oat_classes_[i]->UpdateChecksum(*oat_header_);
95 }
96 return offset;
97}
98
99size_t OatWriter::InitOatCode(size_t offset) {
100 // calculate the offsets within OatHeader to executable code
101 size_t old_offset = offset;
102 // required to be on a new page boundary
103 offset = RoundUp(offset, kPageSize);
104 oat_header_->SetExecutableOffset(offset);
105 executable_offset_padding_length_ = offset - old_offset;
106 return offset;
107}
108
109size_t OatWriter::InitOatCodeDexFiles(size_t offset) {
110 // calculate the offsets within OatMethods
111 size_t oat_class_index = 0;
112 for (size_t i = 0; i != dex_files_->size(); ++i) {
113 const DexFile* dex_file = (*dex_files_)[i];
114 CHECK(dex_file != NULL);
115 offset = InitOatCodeDexFile(offset, oat_class_index, *dex_file);
116 }
117 return offset;
118}
119
120size_t OatWriter::InitOatCodeDexFile(size_t offset,
121 size_t& oat_class_index,
122 const DexFile& dex_file) {
123 for (size_t class_def_index = 0;
124 class_def_index < dex_file.NumClassDefs();
125 class_def_index++, oat_class_index++) {
126 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
127 offset = InitOatCodeClassDef(offset, oat_class_index, dex_file, class_def);
128 oat_methods_[oat_class_index]->UpdateChecksum(*oat_header_);
129 }
130 return offset;
131}
132
133size_t OatWriter::InitOatCodeClassDef(size_t offset,
134 size_t oat_class_index,
135 const DexFile& dex_file,
136 const DexFile::ClassDef& class_def) {
137 const byte* class_data = dex_file.GetClassData(class_def);
138 DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
139 size_t num_virtual_methods = header.virtual_methods_size_;
140 const char* descriptor = dex_file.GetClassDescriptor(class_def);
141
142 // TODO: remove code ByteArrays from Class/Method (and therefore ClassLoader)
143 // TODO: don't write code for shared stubs
144 Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, class_loader_);
145 CHECK(klass != NULL) << descriptor;
146 CHECK_EQ(klass->GetClassLoader(), class_loader_);
147 CHECK_EQ(oat_methods_[oat_class_index]->method_offsets_.size(),
148 klass->NumDirectMethods() + num_virtual_methods);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700149 size_t class_def_method_index = 0;
150 for (size_t i = 0; i < klass->NumDirectMethods(); i++, class_def_method_index++) {
151 Method* method = klass->GetDirectMethod(i);
152 CHECK(method != NULL) << descriptor << " direct " << i;
153 offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method);
154 }
155 // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods
156 for (size_t i = 0; i < num_virtual_methods; i++, class_def_method_index++) {
157 Method* method = klass->GetVirtualMethod(i);
158 CHECK(method != NULL) << descriptor << " virtual " << i;
159 offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method);
160 }
161 return offset;
162}
163
164size_t OatWriter::InitOatCodeMethod(size_t offset,
165 size_t oat_class_index,
166 size_t class_def_method_index,
167 Method* method) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700168 // derived from CompiledMethod if available
169 uint32_t code_offset = 0;
170 uint32_t frame_size_in_bytes = kStackAlignment;
171 uint32_t return_pc_offset_in_bytes = 0;
172 uint32_t core_spill_mask = 0;
173 uint32_t fp_spill_mask = 0;
174 uint32_t mapping_table_offset = 0;
175 uint32_t vmap_table_offset = 0;
176 // derived from CompiledInvokeStub if available
177 uint32_t invoke_stub_offset = 0;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700178
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700179 const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
180 if (compiled_method != NULL) {
181
182 offset = compiled_method->AlignCode(offset);
Elliott Hughes06b37d92011-10-16 11:51:29 -0700183 DCHECK_ALIGNED(offset, kArmAlignment);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700184 const std::vector<uint8_t>& code = compiled_method->GetCode();
185 size_t code_size = code.size() * sizeof(code[0]);
186 uint32_t thumb_offset = compiled_method->CodeDelta();
187 code_offset = (code_size == 0) ? 0 : offset + thumb_offset;
188 offset += code_size;
189 oat_header_->UpdateChecksum(&code[0], code_size);
190
191 frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
192 return_pc_offset_in_bytes = compiled_method->GetReturnPcOffsetInBytes();
193 core_spill_mask = compiled_method->GetCoreSpillMask();
194 fp_spill_mask = compiled_method->GetFpSpillMask();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700195 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700196
197 offset += sizeof(frame_size_in_bytes);
198 oat_header_->UpdateChecksum(&frame_size_in_bytes, sizeof(frame_size_in_bytes));
199
200 offset += sizeof(return_pc_offset_in_bytes);
201 oat_header_->UpdateChecksum(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes));
202
203 offset += sizeof(core_spill_mask);
204 oat_header_->UpdateChecksum(&core_spill_mask, sizeof(core_spill_mask));
205
206 offset += sizeof(fp_spill_mask);
207 oat_header_->UpdateChecksum(&fp_spill_mask, sizeof(fp_spill_mask));
208
209 if (compiled_method != NULL) {
210
211 const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
212 size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
213 mapping_table_offset = (mapping_table_size == 0) ? 0 : offset;
214 offset += mapping_table_size;
215 oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size);
216
217 const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
218 size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
219 vmap_table_offset = (vmap_table_size == 0) ? 0 : offset;
220 offset += vmap_table_size;
221 oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size);
222 }
223
224 const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
225 if (compiled_invoke_stub != NULL) {
226 offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
Elliott Hughes06b37d92011-10-16 11:51:29 -0700227 DCHECK_ALIGNED(offset, kArmAlignment);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700228 const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
229 size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
230 invoke_stub_offset = (invoke_stub_size == 0) ? 0 : offset;
231 offset += invoke_stub_size;
232 oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size);
233 }
234
235 oat_methods_[oat_class_index]->method_offsets_[class_def_method_index]
236 = OatMethodOffsets(code_offset,
237 frame_size_in_bytes,
238 return_pc_offset_in_bytes,
239 core_spill_mask,
240 fp_spill_mask,
241 mapping_table_offset,
242 vmap_table_offset,
243 invoke_stub_offset);
244
245 // Note that we leave the offset and values back in the Method where ImageWriter will find them
246 method->SetOatCodeOffset(code_offset);
247 method->SetFrameSizeInBytes(frame_size_in_bytes);
248 method->SetReturnPcOffsetInBytes(return_pc_offset_in_bytes);
249 method->SetCoreSpillMask(core_spill_mask);
250 method->SetFpSpillMask(fp_spill_mask);
251 method->SetOatMappingTableOffset(mapping_table_offset);
252 method->SetOatVmapTableOffset(vmap_table_offset);
253 method->SetOatInvokeStubOffset(invoke_stub_offset);
254
Brian Carlstrome24fa612011-09-29 00:53:55 -0700255 return offset;
256}
257
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700258#define DCHECK_CODE_OFFSET() \
259 DCHECK_EQ(static_cast<off_t>(code_offset), lseek(file->Fd(), 0, SEEK_CUR))
260
Brian Carlstrome24fa612011-09-29 00:53:55 -0700261bool OatWriter::Write(const std::string& filename) {
262
263 UniquePtr<File> file(OS::OpenFile(filename.c_str(), true));
264 if (file.get() == NULL) {
265 return false;
266 }
267
268 if (!file->WriteFully(oat_header_, sizeof(*oat_header_))) {
269 PLOG(ERROR) << "Failed to write oat header to " << filename;
270 return false;
271 }
272
273 if (!WriteTables(file.get())) {
274 LOG(ERROR) << "Failed to write oat tables to " << filename;
275 return false;
276 }
277
278 size_t code_offset = WriteCode(file.get());
279 if (code_offset == 0) {
280 LOG(ERROR) << "Failed to write oat code to " << filename;
281 return false;
282 }
283
284 code_offset = WriteCodeDexFiles(file.get(), code_offset);
285 if (code_offset == 0) {
286 LOG(ERROR) << "Failed to write oat code for dex files to " << filename;
287 return false;
288 }
289
290 return true;
291}
292
293bool OatWriter::WriteTables(File* file) {
294 for (size_t i = 0; i != oat_dex_files_.size(); ++i) {
295 if (!oat_dex_files_[i]->Write(file)) {
296 PLOG(ERROR) << "Failed to write oat dex information";
297 return false;
298 }
299 }
300 for (size_t i = 0; i != oat_classes_.size(); ++i) {
301 if (!oat_classes_[i]->Write(file)) {
302 PLOG(ERROR) << "Failed to write oat classes information";
303 return false;
304 }
305 }
306 for (size_t i = 0; i != oat_methods_.size(); ++i) {
307 if (!oat_methods_[i]->Write(file)) {
308 PLOG(ERROR) << "Failed to write oat methods information";
309 return false;
310 }
311 }
312 return true;
313}
314
315size_t OatWriter::WriteCode(File* file) {
316 uint32_t code_offset = oat_header_->GetExecutableOffset();
317 off_t new_offset = lseek(file->Fd(), executable_offset_padding_length_, SEEK_CUR);
318 if (static_cast<uint32_t>(new_offset) != code_offset) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700319 PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset
320 << " Expected: " << code_offset;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700321 return 0;
322 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700323 DCHECK_CODE_OFFSET();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700324 return code_offset;
325}
326
327size_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) {
328 for (size_t i = 0; i != oat_classes_.size(); ++i) {
329 const DexFile* dex_file = (*dex_files_)[i];
330 CHECK(dex_file != NULL);
331 code_offset = WriteCodeDexFile(file, code_offset, *dex_file);
332 if (code_offset == 0) {
333 return 0;
334 }
335 }
336 return code_offset;
337}
338
339size_t OatWriter::WriteCodeDexFile(File* file,
340 size_t code_offset,
341 const DexFile& dex_file) {
342 for (size_t class_def_index = 0;
343 class_def_index < dex_file.NumClassDefs();
344 class_def_index++) {
345 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
346 code_offset = WriteCodeClassDef(file, code_offset, dex_file, class_def);
347 if (code_offset == 0) {
348 return 0;
349 }
350 }
351 return code_offset;
352}
353
354size_t OatWriter::WriteCodeClassDef(File* file,
355 size_t code_offset,
356 const DexFile& dex_file,
357 const DexFile::ClassDef& class_def) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700358 const byte* class_data = dex_file.GetClassData(class_def);
359 DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
360 size_t num_virtual_methods = header.virtual_methods_size_;
361 const char* descriptor = dex_file.GetClassDescriptor(class_def);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700362 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700363 Class* klass = class_linker->FindClass(descriptor, class_loader_);
364
365 // TODO: deduplicate code arrays
366 // Note that we clear the code array here, image_writer will use GetCodeOffset to find it
367 for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
368 Method* method = klass->GetDirectMethod(i);
369 code_offset = WriteCodeMethod(file, code_offset, method);
370 if (code_offset == 0) {
371 return 0;
372 }
373 }
374 // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods
375 for (size_t i = 0; i < num_virtual_methods; i++) {
376 Method* method = klass->GetVirtualMethod(i);
377 code_offset = WriteCodeMethod(file, code_offset, method);
378 if (code_offset == 0) {
379 return 0;
380 }
381 }
382 for (size_t i = num_virtual_methods; i < klass->NumVirtualMethods(); i++) {
383 Method* method = klass->GetVirtualMethod(i);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700384 CHECK(compiler_->GetCompiledMethod(method) == NULL) << PrettyMethod(method);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700385 }
386 return code_offset;
387}
388
389size_t OatWriter::WriteCodeMethod(File* file,
390 size_t code_offset,
391 Method* method) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700392 const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
393 if (compiled_method != NULL) {
394 uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
Brian Carlstrome24fa612011-09-29 00:53:55 -0700395 uint32_t aligned_code_delta = aligned_code_offset - code_offset;
396 if (aligned_code_delta != 0) {
397 off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
398 if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700399 PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset
400 << " Expected: " << aligned_code_offset;
Brian Carlstrome24fa612011-09-29 00:53:55 -0700401 return false;
402 }
403 code_offset += aligned_code_delta;
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700404 DCHECK_CODE_OFFSET();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700405 }
Elliott Hughes06b37d92011-10-16 11:51:29 -0700406 DCHECK_ALIGNED(code_offset, kArmAlignment);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700407 const std::vector<uint8_t>& code = compiled_method->GetCode();
408 size_t code_size = code.size() * sizeof(code[0]);
409 DCHECK((code_size == 0 && method->GetOatCodeOffset() == 0)
410 || code_offset + compiled_method->CodeDelta() == method->GetOatCodeOffset());
411 if (!file->WriteFully(&code[0], code_size)) {
Brian Carlstrome24fa612011-09-29 00:53:55 -0700412 PLOG(ERROR) << "Failed to write method code for " << PrettyMethod(method);
413 return false;
414 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700415 code_offset += code_size;
416 DCHECK_CODE_OFFSET();
Brian Carlstrome24fa612011-09-29 00:53:55 -0700417 }
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700418
419 uint32_t frame_size_in_bytes = method->GetFrameSizeInBytes();
420 uint32_t return_pc_offset_in_bytes = method->GetReturnPcOffsetInBytes();
421 uint32_t core_spill_mask = method->GetCoreSpillMask();
422 uint32_t fp_spill_mask = method->GetFpSpillMask();
423 if (!file->WriteFully(&frame_size_in_bytes, sizeof(frame_size_in_bytes))) {
424 PLOG(ERROR) << "Failed to write method frame size for " << PrettyMethod(method);
425 return false;
426 }
427 code_offset += sizeof(frame_size_in_bytes);
428 if (!file->WriteFully(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes))) {
429 PLOG(ERROR) << "Failed to write method return pc offset for " << PrettyMethod(method);
430 return false;
431 }
432 code_offset += sizeof(return_pc_offset_in_bytes);
433 if (!file->WriteFully(&core_spill_mask, sizeof(core_spill_mask))) {
434 PLOG(ERROR) << "Failed to write method core spill mask for " << PrettyMethod(method);
435 return false;
436 }
437 code_offset += sizeof(core_spill_mask);
438 if (!file->WriteFully(&fp_spill_mask, sizeof(fp_spill_mask))) {
439 PLOG(ERROR) << "Failed to write method fp spill mask for " << PrettyMethod(method);
440 return false;
441 }
442 code_offset += sizeof(fp_spill_mask);
443
444 if (compiled_method != NULL) {
445 const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable();
446 size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
447 DCHECK((mapping_table_size == 0 && method->GetOatMappingTableOffset() == 0)
448 || code_offset == method->GetOatMappingTableOffset());
449 if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
450 PLOG(ERROR) << "Failed to write mapping table for " << PrettyMethod(method);
451 return false;
452 }
453 code_offset += mapping_table_size;
454 DCHECK_CODE_OFFSET();
455
456 const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable();
457 size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
458 DCHECK((vmap_table_size == 0 && method->GetOatVmapTableOffset() == 0)
459 || code_offset == method->GetOatVmapTableOffset());
460 if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
461 PLOG(ERROR) << "Failed to write vmap table for " << PrettyMethod(method);
462 return false;
463 }
464 code_offset += vmap_table_size;
465 DCHECK_CODE_OFFSET();
466 }
467
468 const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
469 if (compiled_invoke_stub != NULL) {
470 uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
471 compiler_->GetInstructionSet());
472 uint32_t aligned_code_delta = aligned_code_offset - code_offset;
473 if (aligned_code_delta != 0) {
474 off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR);
475 if (static_cast<uint32_t>(new_offset) != aligned_code_offset) {
476 PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset
477 << " Expected: " << aligned_code_offset;
478 return false;
479 }
480 code_offset += aligned_code_delta;
481 DCHECK_CODE_OFFSET();
482 }
Elliott Hughes06b37d92011-10-16 11:51:29 -0700483 DCHECK_ALIGNED(code_offset, kArmAlignment);
Brian Carlstrom3320cf42011-10-04 14:58:28 -0700484 const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode();
485 size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
486 DCHECK((invoke_stub_size == 0 && method->GetOatInvokeStubOffset() == 0)
487 || code_offset == method->GetOatInvokeStubOffset());
488 if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
489 PLOG(ERROR) << "Failed to write invoke stub code for " << PrettyMethod(method);
490 return false;
491 }
492 code_offset += invoke_stub_size;
493 DCHECK_CODE_OFFSET();
494 }
495
Brian Carlstrome24fa612011-09-29 00:53:55 -0700496 return code_offset;
497}
498
499OatWriter::~OatWriter() {
500 delete oat_header_;
501 STLDeleteElements(&oat_dex_files_);
502 STLDeleteElements(&oat_classes_);
503 STLDeleteElements(&oat_methods_);
504}
505
506OatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) {
507 const std::string& location = dex_file.GetLocation();
508 dex_file_location_size_ = location.size();
509 dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data());
510 dex_file_checksum_ = dex_file.GetHeader().checksum_;
511}
512
513size_t OatWriter::OatDexFile::SizeOf() const {
514 return sizeof(dex_file_location_size_)
515 + dex_file_location_size_
516 + sizeof(dex_file_checksum_)
517 + sizeof(classes_offset_);
518}
519
520void OatWriter::OatDexFile::UpdateChecksum(OatHeader& oat_header) const {
521 oat_header.UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_));
522 oat_header.UpdateChecksum(dex_file_location_data_, dex_file_location_size_);
523 oat_header.UpdateChecksum(&dex_file_checksum_, sizeof(dex_file_checksum_));
524 oat_header.UpdateChecksum(&classes_offset_, sizeof(classes_offset_));
525}
526
527bool OatWriter::OatDexFile::Write(File* file) const {
528 if (!file->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) {
529 PLOG(ERROR) << "Failed to write dex file location length";
530 return false;
531 }
532 if (!file->WriteFully(dex_file_location_data_, dex_file_location_size_)) {
533 PLOG(ERROR) << "Failed to write dex file location data";
534 return false;
535 }
536 if (!file->WriteFully(&dex_file_checksum_, sizeof(dex_file_checksum_))) {
537 PLOG(ERROR) << "Failed to write dex file checksum";
538 return false;
539 }
540 if (!file->WriteFully(&classes_offset_, sizeof(classes_offset_))) {
541 PLOG(ERROR) << "Failed to write classes offset";
542 return false;
543 }
544 return true;
545}
546
547OatWriter::OatClasses::OatClasses(const DexFile& dex_file) {
548 methods_offsets_.resize(dex_file.NumClassDefs());
549}
550
551size_t OatWriter::OatClasses::SizeOf() const {
552 return (sizeof(methods_offsets_[0]) * methods_offsets_.size());
553}
554
555void OatWriter::OatClasses::UpdateChecksum(OatHeader& oat_header) const {
556 oat_header.UpdateChecksum(&methods_offsets_[0], SizeOf());
557}
558
559bool OatWriter::OatClasses::Write(File* file) const {
560 if (!file->WriteFully(&methods_offsets_[0], SizeOf())) {
561 PLOG(ERROR) << "Failed to methods offsets";
562 return false;
563 }
564 return true;
565}
566
567OatWriter::OatMethods::OatMethods(uint32_t methods_count) {
568 method_offsets_.resize(methods_count);
569}
570
571size_t OatWriter::OatMethods::SizeOf() const {
572 return (sizeof(method_offsets_[0]) * method_offsets_.size());
573}
574
575void OatWriter::OatMethods::UpdateChecksum(OatHeader& oat_header) const {
576 oat_header.UpdateChecksum(&method_offsets_[0], SizeOf());
577}
578
579bool OatWriter::OatMethods::Write(File* file) const {
580 if (!file->WriteFully(&method_offsets_[0], SizeOf())) {
581 PLOG(ERROR) << "Failed to method offsets";
582 return false;
583 }
584 return true;
585}
586
587} // namespace art