oat_writer.cc revision 387b699e3dc55309023ae2427a76a1ca1d51b0cd
1// 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 13bool OatWriter::Create(const std::string& filename, 14 const ClassLoader* class_loader, 15 const Compiler& compiler) { 16 const std::vector<const DexFile*>& dex_files = ClassLoader::GetCompileTimeClassPath(class_loader); 17 OatWriter oat_writer(dex_files, class_loader, compiler); 18 return oat_writer.Write(filename); 19} 20 21OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, 22 const ClassLoader* class_loader, 23 const Compiler& compiler) { 24 compiler_ = &compiler; 25 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 if (klass == NULL) { 146 LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation(); 147 Thread* thread = Thread::Current(); 148 DCHECK(thread->IsExceptionPending()); 149 thread->ClearException(); 150 return offset; 151 } 152 CHECK_EQ(klass->GetClassLoader(), class_loader_); 153 CHECK_EQ(oat_methods_[oat_class_index]->method_offsets_.size(), 154 klass->NumDirectMethods() + num_virtual_methods); 155 size_t class_def_method_index = 0; 156 for (size_t i = 0; i < klass->NumDirectMethods(); i++, class_def_method_index++) { 157 Method* method = klass->GetDirectMethod(i); 158 CHECK(method != NULL) << descriptor << " direct " << i; 159 offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method); 160 } 161 // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods 162 for (size_t i = 0; i < num_virtual_methods; i++, class_def_method_index++) { 163 Method* method = klass->GetVirtualMethod(i); 164 CHECK(method != NULL) << descriptor << " virtual " << i; 165 offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method); 166 } 167 return offset; 168} 169 170size_t OatWriter::InitOatCodeMethod(size_t offset, 171 size_t oat_class_index, 172 size_t class_def_method_index, 173 Method* method) { 174 // derived from CompiledMethod if available 175 uint32_t code_offset = 0; 176 uint32_t frame_size_in_bytes = kStackAlignment; 177 uint32_t return_pc_offset_in_bytes = 0; 178 uint32_t core_spill_mask = 0; 179 uint32_t fp_spill_mask = 0; 180 uint32_t mapping_table_offset = 0; 181 uint32_t vmap_table_offset = 0; 182 // derived from CompiledInvokeStub if available 183 uint32_t invoke_stub_offset = 0; 184 185 const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method); 186 if (compiled_method != NULL) { 187 offset = compiled_method->AlignCode(offset); 188 DCHECK_ALIGNED(offset, kArmAlignment); 189 const std::vector<uint8_t>& code = compiled_method->GetCode(); 190 size_t code_size = code.size() * sizeof(code[0]); 191 uint32_t thumb_offset = compiled_method->CodeDelta(); 192 code_offset = (code_size == 0) ? 0 : offset + thumb_offset; 193 offset += code_size; 194 oat_header_->UpdateChecksum(&code[0], code_size); 195 196 frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 197 return_pc_offset_in_bytes = compiled_method->GetReturnPcOffsetInBytes(); 198 core_spill_mask = compiled_method->GetCoreSpillMask(); 199 fp_spill_mask = compiled_method->GetFpSpillMask(); 200 } 201 202 offset += sizeof(frame_size_in_bytes); 203 oat_header_->UpdateChecksum(&frame_size_in_bytes, sizeof(frame_size_in_bytes)); 204 205 offset += sizeof(return_pc_offset_in_bytes); 206 oat_header_->UpdateChecksum(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes)); 207 208 offset += sizeof(core_spill_mask); 209 oat_header_->UpdateChecksum(&core_spill_mask, sizeof(core_spill_mask)); 210 211 offset += sizeof(fp_spill_mask); 212 oat_header_->UpdateChecksum(&fp_spill_mask, sizeof(fp_spill_mask)); 213 214 if (compiled_method != NULL) { 215 const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); 216 size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 217 mapping_table_offset = (mapping_table_size == 0) ? 0 : offset; 218 offset += mapping_table_size; 219 oat_header_->UpdateChecksum(&mapping_table[0], mapping_table_size); 220 221 const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); 222 size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 223 vmap_table_offset = (vmap_table_size == 0) ? 0 : offset; 224 offset += vmap_table_size; 225 oat_header_->UpdateChecksum(&vmap_table[0], vmap_table_size); 226 } 227 228 const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method); 229 if (compiled_invoke_stub != NULL) { 230 offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet()); 231 DCHECK_ALIGNED(offset, kArmAlignment); 232 const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 233 size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); 234 invoke_stub_offset = (invoke_stub_size == 0) ? 0 : offset; 235 offset += invoke_stub_size; 236 oat_header_->UpdateChecksum(&invoke_stub[0], invoke_stub_size); 237 } 238 239 oat_methods_[oat_class_index]->method_offsets_[class_def_method_index] 240 = OatMethodOffsets(code_offset, 241 frame_size_in_bytes, 242 return_pc_offset_in_bytes, 243 core_spill_mask, 244 fp_spill_mask, 245 mapping_table_offset, 246 vmap_table_offset, 247 invoke_stub_offset); 248 249 // Note that we leave the offset and values back in the Method where ImageWriter will find them 250 method->SetOatCodeOffset(code_offset); 251 method->SetFrameSizeInBytes(frame_size_in_bytes); 252 method->SetCoreSpillMask(core_spill_mask); 253 method->SetFpSpillMask(fp_spill_mask); 254 method->SetOatMappingTableOffset(mapping_table_offset); 255 method->SetOatVmapTableOffset(vmap_table_offset); 256 method->SetOatInvokeStubOffset(invoke_stub_offset); 257 258 return offset; 259} 260 261#define DCHECK_CODE_OFFSET() \ 262 DCHECK_EQ(static_cast<off_t>(code_offset), lseek(file->Fd(), 0, SEEK_CUR)) 263 264bool OatWriter::Write(const std::string& filename) { 265 UniquePtr<File> file(OS::OpenFile(filename.c_str(), true)); 266 if (file.get() == NULL) { 267 return false; 268 } 269 270 if (!file->WriteFully(oat_header_, sizeof(*oat_header_))) { 271 PLOG(ERROR) << "Failed to write oat header to " << filename; 272 return false; 273 } 274 275 if (!WriteTables(file.get())) { 276 LOG(ERROR) << "Failed to write oat tables to " << filename; 277 return false; 278 } 279 280 size_t code_offset = WriteCode(file.get()); 281 if (code_offset == 0) { 282 LOG(ERROR) << "Failed to write oat code to " << filename; 283 return false; 284 } 285 286 code_offset = WriteCodeDexFiles(file.get(), code_offset); 287 if (code_offset == 0) { 288 LOG(ERROR) << "Failed to write oat code for dex files to " << filename; 289 return false; 290 } 291 292 return true; 293} 294 295bool OatWriter::WriteTables(File* file) { 296 for (size_t i = 0; i != oat_dex_files_.size(); ++i) { 297 if (!oat_dex_files_[i]->Write(file)) { 298 PLOG(ERROR) << "Failed to write oat dex information"; 299 return false; 300 } 301 } 302 for (size_t i = 0; i != oat_classes_.size(); ++i) { 303 if (!oat_classes_[i]->Write(file)) { 304 PLOG(ERROR) << "Failed to write oat classes information"; 305 return false; 306 } 307 } 308 for (size_t i = 0; i != oat_methods_.size(); ++i) { 309 if (!oat_methods_[i]->Write(file)) { 310 PLOG(ERROR) << "Failed to write oat methods information"; 311 return false; 312 } 313 } 314 return true; 315} 316 317size_t OatWriter::WriteCode(File* file) { 318 uint32_t code_offset = oat_header_->GetExecutableOffset(); 319 off_t new_offset = lseek(file->Fd(), executable_offset_padding_length_, SEEK_CUR); 320 if (static_cast<uint32_t>(new_offset) != code_offset) { 321 PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset 322 << " Expected: " << code_offset; 323 return 0; 324 } 325 DCHECK_CODE_OFFSET(); 326 return code_offset; 327} 328 329size_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) { 330 for (size_t i = 0; i != oat_classes_.size(); ++i) { 331 const DexFile* dex_file = (*dex_files_)[i]; 332 CHECK(dex_file != NULL); 333 code_offset = WriteCodeDexFile(file, code_offset, *dex_file); 334 if (code_offset == 0) { 335 return 0; 336 } 337 } 338 return code_offset; 339} 340 341size_t OatWriter::WriteCodeDexFile(File* file, 342 size_t code_offset, 343 const DexFile& dex_file) { 344 for (size_t class_def_index = 0; 345 class_def_index < dex_file.NumClassDefs(); 346 class_def_index++) { 347 const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index); 348 code_offset = WriteCodeClassDef(file, code_offset, dex_file, class_def); 349 if (code_offset == 0) { 350 return 0; 351 } 352 } 353 return code_offset; 354} 355 356size_t OatWriter::WriteCodeClassDef(File* file, 357 size_t code_offset, 358 const DexFile& dex_file, 359 const DexFile::ClassDef& class_def) { 360 const byte* class_data = dex_file.GetClassData(class_def); 361 DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data); 362 size_t num_virtual_methods = header.virtual_methods_size_; 363 const char* descriptor = dex_file.GetClassDescriptor(class_def); 364 ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 365 Class* klass = class_linker->FindClass(descriptor, class_loader_); 366 if (klass == NULL) { 367 LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation(); 368 Thread* thread = Thread::Current(); 369 DCHECK(thread->IsExceptionPending()); 370 thread->ClearException(); 371 return code_offset; 372 } 373 374 // TODO: deduplicate code arrays 375 // Note that we clear the code array here, image_writer will use GetCodeOffset to find it 376 for (size_t i = 0; i < klass->NumDirectMethods(); i++) { 377 Method* method = klass->GetDirectMethod(i); 378 code_offset = WriteCodeMethod(file, code_offset, method); 379 if (code_offset == 0) { 380 return 0; 381 } 382 } 383 // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods 384 for (size_t i = 0; i < num_virtual_methods; i++) { 385 Method* method = klass->GetVirtualMethod(i); 386 code_offset = WriteCodeMethod(file, code_offset, method); 387 if (code_offset == 0) { 388 return 0; 389 } 390 } 391 for (size_t i = num_virtual_methods; i < klass->NumVirtualMethods(); i++) { 392 Method* method = klass->GetVirtualMethod(i); 393 CHECK(compiler_->GetCompiledMethod(method) == NULL) << PrettyMethod(method); 394 } 395 return code_offset; 396} 397 398size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, Method* method) { 399 const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method); 400 if (compiled_method != NULL) { 401 uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset); 402 uint32_t aligned_code_delta = aligned_code_offset - code_offset; 403 if (aligned_code_delta != 0) { 404 off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); 405 if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { 406 PLOG(ERROR) << "Failed to seek to align oat code. Actual: " << new_offset 407 << " Expected: " << aligned_code_offset; 408 return false; 409 } 410 code_offset += aligned_code_delta; 411 DCHECK_CODE_OFFSET(); 412 } 413 DCHECK_ALIGNED(code_offset, kArmAlignment); 414 const std::vector<uint8_t>& code = compiled_method->GetCode(); 415 size_t code_size = code.size() * sizeof(code[0]); 416 DCHECK((code_size == 0 && method->GetOatCodeOffset() == 0) 417 || code_offset + compiled_method->CodeDelta() == method->GetOatCodeOffset()); 418 if (!file->WriteFully(&code[0], code_size)) { 419 PLOG(ERROR) << "Failed to write method code for " << PrettyMethod(method); 420 return false; 421 } 422 code_offset += code_size; 423 DCHECK_CODE_OFFSET(); 424 } 425 426 uint32_t frame_size_in_bytes = method->GetFrameSizeInBytes(); 427 uint32_t return_pc_offset_in_bytes = method->GetReturnPcOffsetInBytes(); 428 uint32_t core_spill_mask = method->GetCoreSpillMask(); 429 uint32_t fp_spill_mask = method->GetFpSpillMask(); 430 if (!file->WriteFully(&frame_size_in_bytes, sizeof(frame_size_in_bytes))) { 431 PLOG(ERROR) << "Failed to write method frame size for " << PrettyMethod(method); 432 return false; 433 } 434 code_offset += sizeof(frame_size_in_bytes); 435 if (!file->WriteFully(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes))) { 436 PLOG(ERROR) << "Failed to write method return pc offset for " << PrettyMethod(method); 437 return false; 438 } 439 code_offset += sizeof(return_pc_offset_in_bytes); 440 if (!file->WriteFully(&core_spill_mask, sizeof(core_spill_mask))) { 441 PLOG(ERROR) << "Failed to write method core spill mask for " << PrettyMethod(method); 442 return false; 443 } 444 code_offset += sizeof(core_spill_mask); 445 if (!file->WriteFully(&fp_spill_mask, sizeof(fp_spill_mask))) { 446 PLOG(ERROR) << "Failed to write method fp spill mask for " << PrettyMethod(method); 447 return false; 448 } 449 code_offset += sizeof(fp_spill_mask); 450 451 if (compiled_method != NULL) { 452 const std::vector<uint32_t>& mapping_table = compiled_method->GetMappingTable(); 453 size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]); 454 DCHECK((mapping_table_size == 0 && method->GetOatMappingTableOffset() == 0) 455 || code_offset == method->GetOatMappingTableOffset()); 456 if (!file->WriteFully(&mapping_table[0], mapping_table_size)) { 457 PLOG(ERROR) << "Failed to write mapping table for " << PrettyMethod(method); 458 return false; 459 } 460 code_offset += mapping_table_size; 461 DCHECK_CODE_OFFSET(); 462 463 const std::vector<uint16_t>& vmap_table = compiled_method->GetVmapTable(); 464 size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]); 465 DCHECK((vmap_table_size == 0 && method->GetOatVmapTableOffset() == 0) 466 || code_offset == method->GetOatVmapTableOffset()); 467 if (!file->WriteFully(&vmap_table[0], vmap_table_size)) { 468 PLOG(ERROR) << "Failed to write vmap table for " << PrettyMethod(method); 469 return false; 470 } 471 code_offset += vmap_table_size; 472 DCHECK_CODE_OFFSET(); 473 } 474 475 const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method); 476 if (compiled_invoke_stub != NULL) { 477 uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset, 478 compiler_->GetInstructionSet()); 479 uint32_t aligned_code_delta = aligned_code_offset - code_offset; 480 if (aligned_code_delta != 0) { 481 off_t new_offset = lseek(file->Fd(), aligned_code_delta, SEEK_CUR); 482 if (static_cast<uint32_t>(new_offset) != aligned_code_offset) { 483 PLOG(ERROR) << "Failed to seek to align invoke stub code. Actual: " << new_offset 484 << " Expected: " << aligned_code_offset; 485 return false; 486 } 487 code_offset += aligned_code_delta; 488 DCHECK_CODE_OFFSET(); 489 } 490 DCHECK_ALIGNED(code_offset, kArmAlignment); 491 const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 492 size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]); 493 DCHECK((invoke_stub_size == 0 && method->GetOatInvokeStubOffset() == 0) 494 || code_offset == method->GetOatInvokeStubOffset()) << PrettyMethod(method); 495 if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) { 496 PLOG(ERROR) << "Failed to write invoke stub code for " << PrettyMethod(method); 497 return false; 498 } 499 code_offset += invoke_stub_size; 500 DCHECK_CODE_OFFSET(); 501 } 502 503 return code_offset; 504} 505 506OatWriter::~OatWriter() { 507 delete oat_header_; 508 STLDeleteElements(&oat_dex_files_); 509 STLDeleteElements(&oat_classes_); 510 STLDeleteElements(&oat_methods_); 511} 512 513OatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) { 514 const std::string& location = dex_file.GetLocation(); 515 dex_file_location_size_ = location.size(); 516 dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data()); 517 dex_file_checksum_ = dex_file.GetHeader().checksum_; 518} 519 520size_t OatWriter::OatDexFile::SizeOf() const { 521 return sizeof(dex_file_location_size_) 522 + dex_file_location_size_ 523 + sizeof(dex_file_checksum_) 524 + sizeof(classes_offset_); 525} 526 527void OatWriter::OatDexFile::UpdateChecksum(OatHeader& oat_header) const { 528 oat_header.UpdateChecksum(&dex_file_location_size_, sizeof(dex_file_location_size_)); 529 oat_header.UpdateChecksum(dex_file_location_data_, dex_file_location_size_); 530 oat_header.UpdateChecksum(&dex_file_checksum_, sizeof(dex_file_checksum_)); 531 oat_header.UpdateChecksum(&classes_offset_, sizeof(classes_offset_)); 532} 533 534bool OatWriter::OatDexFile::Write(File* file) const { 535 if (!file->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) { 536 PLOG(ERROR) << "Failed to write dex file location length"; 537 return false; 538 } 539 if (!file->WriteFully(dex_file_location_data_, dex_file_location_size_)) { 540 PLOG(ERROR) << "Failed to write dex file location data"; 541 return false; 542 } 543 if (!file->WriteFully(&dex_file_checksum_, sizeof(dex_file_checksum_))) { 544 PLOG(ERROR) << "Failed to write dex file checksum"; 545 return false; 546 } 547 if (!file->WriteFully(&classes_offset_, sizeof(classes_offset_))) { 548 PLOG(ERROR) << "Failed to write classes offset"; 549 return false; 550 } 551 return true; 552} 553 554OatWriter::OatClasses::OatClasses(const DexFile& dex_file) { 555 methods_offsets_.resize(dex_file.NumClassDefs()); 556} 557 558size_t OatWriter::OatClasses::SizeOf() const { 559 return (sizeof(methods_offsets_[0]) * methods_offsets_.size()); 560} 561 562void OatWriter::OatClasses::UpdateChecksum(OatHeader& oat_header) const { 563 oat_header.UpdateChecksum(&methods_offsets_[0], SizeOf()); 564} 565 566bool OatWriter::OatClasses::Write(File* file) const { 567 if (!file->WriteFully(&methods_offsets_[0], SizeOf())) { 568 PLOG(ERROR) << "Failed to methods offsets"; 569 return false; 570 } 571 return true; 572} 573 574OatWriter::OatMethods::OatMethods(uint32_t methods_count) { 575 method_offsets_.resize(methods_count); 576} 577 578size_t OatWriter::OatMethods::SizeOf() const { 579 return (sizeof(method_offsets_[0]) * method_offsets_.size()); 580} 581 582void OatWriter::OatMethods::UpdateChecksum(OatHeader& oat_header) const { 583 oat_header.UpdateChecksum(&method_offsets_[0], SizeOf()); 584} 585 586bool OatWriter::OatMethods::Write(File* file) const { 587 if (!file->WriteFully(&method_offsets_[0], SizeOf())) { 588 PLOG(ERROR) << "Failed to method offsets"; 589 return false; 590 } 591 return true; 592} 593 594} // namespace art 595