1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "oat_writer.h" 18 19 #include <unistd.h> 20 #include <zlib.h> 21 22 #include "arch/arm64/instruction_set_features_arm64.h" 23 #include "art_method-inl.h" 24 #include "base/allocator.h" 25 #include "base/bit_vector.h" 26 #include "base/file_magic.h" 27 #include "base/stl_util.h" 28 #include "base/unix_file/fd_file.h" 29 #include "class_linker.h" 30 #include "compiled_class.h" 31 #include "compiled_method.h" 32 #include "debug/method_debug_info.h" 33 #include "dex/verification_results.h" 34 #include "dex_file-inl.h" 35 #include "driver/compiler_driver.h" 36 #include "driver/compiler_options.h" 37 #include "gc/space/image_space.h" 38 #include "gc/space/space.h" 39 #include "handle_scope-inl.h" 40 #include "image_writer.h" 41 #include "linker/multi_oat_relative_patcher.h" 42 #include "linker/output_stream.h" 43 #include "mirror/array.h" 44 #include "mirror/class_loader.h" 45 #include "mirror/dex_cache-inl.h" 46 #include "mirror/object-inl.h" 47 #include "oat_quick_method_header.h" 48 #include "os.h" 49 #include "safe_map.h" 50 #include "scoped_thread_state_change.h" 51 #include "type_lookup_table.h" 52 #include "utils/dex_cache_arrays_layout-inl.h" 53 #include "verifier/method_verifier.h" 54 #include "zip_archive.h" 55 56 namespace art { 57 58 namespace { // anonymous namespace 59 60 typedef DexFile::Header __attribute__((aligned(1))) UnalignedDexFileHeader; 61 62 const UnalignedDexFileHeader* AsUnalignedDexFileHeader(const uint8_t* raw_data) { 63 return reinterpret_cast<const UnalignedDexFileHeader*>(raw_data); 64 } 65 66 class ChecksumUpdatingOutputStream : public OutputStream { 67 public: 68 ChecksumUpdatingOutputStream(OutputStream* out, OatHeader* oat_header) 69 : OutputStream(out->GetLocation()), out_(out), oat_header_(oat_header) { } 70 71 bool WriteFully(const void* buffer, size_t byte_count) OVERRIDE { 72 oat_header_->UpdateChecksum(buffer, byte_count); 73 return out_->WriteFully(buffer, byte_count); 74 } 75 76 off_t Seek(off_t offset, Whence whence) OVERRIDE { 77 return out_->Seek(offset, whence); 78 } 79 80 bool Flush() OVERRIDE { 81 return out_->Flush(); 82 } 83 84 private: 85 OutputStream* const out_; 86 OatHeader* const oat_header_; 87 }; 88 89 } // anonymous namespace 90 91 // Defines the location of the raw dex file to write. 92 class OatWriter::DexFileSource { 93 public: 94 explicit DexFileSource(ZipEntry* zip_entry) 95 : type_(kZipEntry), source_(zip_entry) { 96 DCHECK(source_ != nullptr); 97 } 98 99 explicit DexFileSource(File* raw_file) 100 : type_(kRawFile), source_(raw_file) { 101 DCHECK(source_ != nullptr); 102 } 103 104 explicit DexFileSource(const uint8_t* dex_file) 105 : type_(kRawData), source_(dex_file) { 106 DCHECK(source_ != nullptr); 107 } 108 109 bool IsZipEntry() const { return type_ == kZipEntry; } 110 bool IsRawFile() const { return type_ == kRawFile; } 111 bool IsRawData() const { return type_ == kRawData; } 112 113 ZipEntry* GetZipEntry() const { 114 DCHECK(IsZipEntry()); 115 DCHECK(source_ != nullptr); 116 return static_cast<ZipEntry*>(const_cast<void*>(source_)); 117 } 118 119 File* GetRawFile() const { 120 DCHECK(IsRawFile()); 121 DCHECK(source_ != nullptr); 122 return static_cast<File*>(const_cast<void*>(source_)); 123 } 124 125 const uint8_t* GetRawData() const { 126 DCHECK(IsRawData()); 127 DCHECK(source_ != nullptr); 128 return static_cast<const uint8_t*>(source_); 129 } 130 131 void Clear() { 132 type_ = kNone; 133 source_ = nullptr; 134 } 135 136 private: 137 enum Type { 138 kNone, 139 kZipEntry, 140 kRawFile, 141 kRawData, 142 }; 143 144 Type type_; 145 const void* source_; 146 }; 147 148 class OatWriter::OatClass { 149 public: 150 OatClass(size_t offset, 151 const dchecked_vector<CompiledMethod*>& compiled_methods, 152 uint32_t num_non_null_compiled_methods, 153 mirror::Class::Status status); 154 OatClass(OatClass&& src) = default; 155 size_t GetOatMethodOffsetsOffsetFromOatHeader(size_t class_def_method_index_) const; 156 size_t GetOatMethodOffsetsOffsetFromOatClass(size_t class_def_method_index_) const; 157 size_t SizeOf() const; 158 bool Write(OatWriter* oat_writer, OutputStream* out, const size_t file_offset) const; 159 160 CompiledMethod* GetCompiledMethod(size_t class_def_method_index) const { 161 return compiled_methods_[class_def_method_index]; 162 } 163 164 // Offset of start of OatClass from beginning of OatHeader. It is 165 // used to validate file position when writing. 166 size_t offset_; 167 168 // CompiledMethods for each class_def_method_index, or null if no method is available. 169 dchecked_vector<CompiledMethod*> compiled_methods_; 170 171 // Offset from OatClass::offset_ to the OatMethodOffsets for the 172 // class_def_method_index. If 0, it means the corresponding 173 // CompiledMethod entry in OatClass::compiled_methods_ should be 174 // null and that the OatClass::type_ should be kOatClassBitmap. 175 dchecked_vector<uint32_t> oat_method_offsets_offsets_from_oat_class_; 176 177 // Data to write. 178 179 static_assert(mirror::Class::Status::kStatusMax < (1 << 16), "class status won't fit in 16bits"); 180 int16_t status_; 181 182 static_assert(OatClassType::kOatClassMax < (1 << 16), "oat_class type won't fit in 16bits"); 183 uint16_t type_; 184 185 uint32_t method_bitmap_size_; 186 187 // bit vector indexed by ClassDef method index. When 188 // OatClassType::type_ is kOatClassBitmap, a set bit indicates the 189 // method has an OatMethodOffsets in methods_offsets_, otherwise 190 // the entry was ommited to save space. If OatClassType::type_ is 191 // not is kOatClassBitmap, the bitmap will be null. 192 std::unique_ptr<BitVector> method_bitmap_; 193 194 // OatMethodOffsets and OatMethodHeaders for each CompiledMethod 195 // present in the OatClass. Note that some may be missing if 196 // OatClass::compiled_methods_ contains null values (and 197 // oat_method_offsets_offsets_from_oat_class_ should contain 0 198 // values in this case). 199 dchecked_vector<OatMethodOffsets> method_offsets_; 200 dchecked_vector<OatQuickMethodHeader> method_headers_; 201 202 private: 203 size_t GetMethodOffsetsRawSize() const { 204 return method_offsets_.size() * sizeof(method_offsets_[0]); 205 } 206 207 DISALLOW_COPY_AND_ASSIGN(OatClass); 208 }; 209 210 class OatWriter::OatDexFile { 211 public: 212 OatDexFile(const char* dex_file_location, 213 DexFileSource source, 214 CreateTypeLookupTable create_type_lookup_table); 215 OatDexFile(OatDexFile&& src) = default; 216 217 const char* GetLocation() const { 218 return dex_file_location_data_; 219 } 220 221 void ReserveTypeLookupTable(OatWriter* oat_writer); 222 void ReserveClassOffsets(OatWriter* oat_writer); 223 224 size_t SizeOf() const; 225 bool Write(OatWriter* oat_writer, OutputStream* out) const; 226 bool WriteClassOffsets(OatWriter* oat_writer, OutputStream* out); 227 228 // The source of the dex file. 229 DexFileSource source_; 230 231 // Whether to create the type lookup table. 232 CreateTypeLookupTable create_type_lookup_table_; 233 234 // Dex file size. Initialized when writing the dex file. 235 size_t dex_file_size_; 236 237 // Offset of start of OatDexFile from beginning of OatHeader. It is 238 // used to validate file position when writing. 239 size_t offset_; 240 241 // Data to write. 242 uint32_t dex_file_location_size_; 243 const char* dex_file_location_data_; 244 uint32_t dex_file_location_checksum_; 245 uint32_t dex_file_offset_; 246 uint32_t class_offsets_offset_; 247 uint32_t lookup_table_offset_; 248 249 // Data to write to a separate section. 250 dchecked_vector<uint32_t> class_offsets_; 251 252 private: 253 size_t GetClassOffsetsRawSize() const { 254 return class_offsets_.size() * sizeof(class_offsets_[0]); 255 } 256 257 DISALLOW_COPY_AND_ASSIGN(OatDexFile); 258 }; 259 260 #define DCHECK_OFFSET() \ 261 DCHECK_EQ(static_cast<off_t>(file_offset + relative_offset), out->Seek(0, kSeekCurrent)) \ 262 << "file_offset=" << file_offset << " relative_offset=" << relative_offset 263 264 #define DCHECK_OFFSET_() \ 265 DCHECK_EQ(static_cast<off_t>(file_offset + offset_), out->Seek(0, kSeekCurrent)) \ 266 << "file_offset=" << file_offset << " offset_=" << offset_ 267 268 OatWriter::OatWriter(bool compiling_boot_image, TimingLogger* timings) 269 : write_state_(WriteState::kAddingDexFileSources), 270 timings_(timings), 271 raw_dex_files_(), 272 zip_archives_(), 273 zipped_dex_files_(), 274 zipped_dex_file_locations_(), 275 compiler_driver_(nullptr), 276 image_writer_(nullptr), 277 compiling_boot_image_(compiling_boot_image), 278 dex_files_(nullptr), 279 size_(0u), 280 bss_size_(0u), 281 oat_data_offset_(0u), 282 oat_header_(nullptr), 283 size_dex_file_alignment_(0), 284 size_executable_offset_alignment_(0), 285 size_oat_header_(0), 286 size_oat_header_key_value_store_(0), 287 size_dex_file_(0), 288 size_interpreter_to_interpreter_bridge_(0), 289 size_interpreter_to_compiled_code_bridge_(0), 290 size_jni_dlsym_lookup_(0), 291 size_quick_generic_jni_trampoline_(0), 292 size_quick_imt_conflict_trampoline_(0), 293 size_quick_resolution_trampoline_(0), 294 size_quick_to_interpreter_bridge_(0), 295 size_trampoline_alignment_(0), 296 size_method_header_(0), 297 size_code_(0), 298 size_code_alignment_(0), 299 size_relative_call_thunks_(0), 300 size_misc_thunks_(0), 301 size_vmap_table_(0), 302 size_oat_dex_file_location_size_(0), 303 size_oat_dex_file_location_data_(0), 304 size_oat_dex_file_location_checksum_(0), 305 size_oat_dex_file_offset_(0), 306 size_oat_dex_file_class_offsets_offset_(0), 307 size_oat_dex_file_lookup_table_offset_(0), 308 size_oat_lookup_table_alignment_(0), 309 size_oat_lookup_table_(0), 310 size_oat_class_offsets_alignment_(0), 311 size_oat_class_offsets_(0), 312 size_oat_class_type_(0), 313 size_oat_class_status_(0), 314 size_oat_class_method_bitmaps_(0), 315 size_oat_class_method_offsets_(0), 316 relative_patcher_(nullptr), 317 absolute_patch_locations_() { 318 } 319 320 bool OatWriter::AddDexFileSource(const char* filename, 321 const char* location, 322 CreateTypeLookupTable create_type_lookup_table) { 323 DCHECK(write_state_ == WriteState::kAddingDexFileSources); 324 uint32_t magic; 325 std::string error_msg; 326 ScopedFd fd(OpenAndReadMagic(filename, &magic, &error_msg)); 327 if (fd.get() == -1) { 328 PLOG(ERROR) << "Failed to read magic number from dex file: '" << filename << "'"; 329 return false; 330 } else if (IsDexMagic(magic)) { 331 // The file is open for reading, not writing, so it's OK to let the File destructor 332 // close it without checking for explicit Close(), so pass checkUsage = false. 333 raw_dex_files_.emplace_back(new File(fd.release(), location, /* checkUsage */ false)); 334 oat_dex_files_.emplace_back(location, 335 DexFileSource(raw_dex_files_.back().get()), 336 create_type_lookup_table); 337 } else if (IsZipMagic(magic)) { 338 if (!AddZippedDexFilesSource(std::move(fd), location, create_type_lookup_table)) { 339 return false; 340 } 341 } else { 342 LOG(ERROR) << "Expected valid zip or dex file: '" << filename << "'"; 343 return false; 344 } 345 return true; 346 } 347 348 // Add dex file source(s) from a zip file specified by a file handle. 349 bool OatWriter::AddZippedDexFilesSource(ScopedFd&& zip_fd, 350 const char* location, 351 CreateTypeLookupTable create_type_lookup_table) { 352 DCHECK(write_state_ == WriteState::kAddingDexFileSources); 353 std::string error_msg; 354 zip_archives_.emplace_back(ZipArchive::OpenFromFd(zip_fd.release(), location, &error_msg)); 355 ZipArchive* zip_archive = zip_archives_.back().get(); 356 if (zip_archive == nullptr) { 357 LOG(ERROR) << "Failed to open zip from file descriptor for '" << location << "': " 358 << error_msg; 359 return false; 360 } 361 for (size_t i = 0; ; ++i) { 362 std::string entry_name = DexFile::GetMultiDexClassesDexName(i); 363 std::unique_ptr<ZipEntry> entry(zip_archive->Find(entry_name.c_str(), &error_msg)); 364 if (entry == nullptr) { 365 break; 366 } 367 zipped_dex_files_.push_back(std::move(entry)); 368 zipped_dex_file_locations_.push_back(DexFile::GetMultiDexLocation(i, location)); 369 const char* full_location = zipped_dex_file_locations_.back().c_str(); 370 oat_dex_files_.emplace_back(full_location, 371 DexFileSource(zipped_dex_files_.back().get()), 372 create_type_lookup_table); 373 } 374 if (zipped_dex_file_locations_.empty()) { 375 LOG(ERROR) << "No dex files in zip file '" << location << "': " << error_msg; 376 return false; 377 } 378 return true; 379 } 380 381 // Add dex file source from raw memory. 382 bool OatWriter::AddRawDexFileSource(const ArrayRef<const uint8_t>& data, 383 const char* location, 384 uint32_t location_checksum, 385 CreateTypeLookupTable create_type_lookup_table) { 386 DCHECK(write_state_ == WriteState::kAddingDexFileSources); 387 if (data.size() < sizeof(DexFile::Header)) { 388 LOG(ERROR) << "Provided data is shorter than dex file header. size: " 389 << data.size() << " File: " << location; 390 return false; 391 } 392 if (!ValidateDexFileHeader(data.data(), location)) { 393 return false; 394 } 395 const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(data.data()); 396 if (data.size() < header->file_size_) { 397 LOG(ERROR) << "Truncated dex file data. Data size: " << data.size() 398 << " file size from header: " << header->file_size_ << " File: " << location; 399 return false; 400 } 401 402 oat_dex_files_.emplace_back(location, DexFileSource(data.data()), create_type_lookup_table); 403 oat_dex_files_.back().dex_file_location_checksum_ = location_checksum; 404 return true; 405 } 406 407 dchecked_vector<const char*> OatWriter::GetSourceLocations() const { 408 dchecked_vector<const char*> locations; 409 locations.reserve(oat_dex_files_.size()); 410 for (const OatDexFile& oat_dex_file : oat_dex_files_) { 411 locations.push_back(oat_dex_file.GetLocation()); 412 } 413 return locations; 414 } 415 416 bool OatWriter::WriteAndOpenDexFiles( 417 OutputStream* rodata, 418 File* file, 419 InstructionSet instruction_set, 420 const InstructionSetFeatures* instruction_set_features, 421 SafeMap<std::string, std::string>* key_value_store, 422 bool verify, 423 /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map, 424 /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) { 425 CHECK(write_state_ == WriteState::kAddingDexFileSources); 426 427 size_t offset = InitOatHeader(instruction_set, 428 instruction_set_features, 429 dchecked_integral_cast<uint32_t>(oat_dex_files_.size()), 430 key_value_store); 431 offset = InitOatDexFiles(offset); 432 size_ = offset; 433 434 std::unique_ptr<MemMap> dex_files_map; 435 std::vector<std::unique_ptr<const DexFile>> dex_files; 436 if (!WriteDexFiles(rodata, file)) { 437 return false; 438 } 439 // Reserve space for type lookup tables and update type_lookup_table_offset_. 440 for (OatDexFile& oat_dex_file : oat_dex_files_) { 441 oat_dex_file.ReserveTypeLookupTable(this); 442 } 443 size_t size_after_type_lookup_tables = size_; 444 // Reserve space for class offsets and update class_offsets_offset_. 445 for (OatDexFile& oat_dex_file : oat_dex_files_) { 446 oat_dex_file.ReserveClassOffsets(this); 447 } 448 ChecksumUpdatingOutputStream checksum_updating_rodata(rodata, oat_header_.get()); 449 if (!WriteOatDexFiles(&checksum_updating_rodata) || 450 !ExtendForTypeLookupTables(rodata, file, size_after_type_lookup_tables) || 451 !OpenDexFiles(file, verify, &dex_files_map, &dex_files) || 452 !WriteTypeLookupTables(dex_files_map.get(), dex_files)) { 453 return false; 454 } 455 456 // Do a bulk checksum update for Dex[] and TypeLookupTable[]. Doing it piece by 457 // piece would be difficult because we're not using the OutpuStream directly. 458 if (!oat_dex_files_.empty()) { 459 size_t size = size_after_type_lookup_tables - oat_dex_files_[0].dex_file_offset_; 460 oat_header_->UpdateChecksum(dex_files_map->Begin(), size); 461 } 462 463 *opened_dex_files_map = std::move(dex_files_map); 464 *opened_dex_files = std::move(dex_files); 465 write_state_ = WriteState::kPrepareLayout; 466 return true; 467 } 468 469 void OatWriter::PrepareLayout(const CompilerDriver* compiler, 470 ImageWriter* image_writer, 471 const std::vector<const DexFile*>& dex_files, 472 linker::MultiOatRelativePatcher* relative_patcher) { 473 CHECK(write_state_ == WriteState::kPrepareLayout); 474 475 compiler_driver_ = compiler; 476 image_writer_ = image_writer; 477 dex_files_ = &dex_files; 478 relative_patcher_ = relative_patcher; 479 SetMultiOatRelativePatcherAdjustment(); 480 481 if (compiling_boot_image_) { 482 CHECK(image_writer_ != nullptr); 483 } 484 InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); 485 CHECK_EQ(instruction_set, oat_header_->GetInstructionSet()); 486 487 uint32_t offset = size_; 488 { 489 TimingLogger::ScopedTiming split("InitOatClasses", timings_); 490 offset = InitOatClasses(offset); 491 } 492 { 493 TimingLogger::ScopedTiming split("InitOatMaps", timings_); 494 offset = InitOatMaps(offset); 495 } 496 { 497 TimingLogger::ScopedTiming split("InitOatCode", timings_); 498 offset = InitOatCode(offset); 499 } 500 { 501 TimingLogger::ScopedTiming split("InitOatCodeDexFiles", timings_); 502 offset = InitOatCodeDexFiles(offset); 503 } 504 size_ = offset; 505 506 if (!HasBootImage()) { 507 // Allocate space for app dex cache arrays in the .bss section. 508 size_t bss_start = RoundUp(size_, kPageSize); 509 size_t pointer_size = GetInstructionSetPointerSize(instruction_set); 510 bss_size_ = 0u; 511 for (const DexFile* dex_file : *dex_files_) { 512 dex_cache_arrays_offsets_.Put(dex_file, bss_start + bss_size_); 513 DexCacheArraysLayout layout(pointer_size, dex_file); 514 bss_size_ += layout.Size(); 515 } 516 } 517 518 CHECK_EQ(dex_files_->size(), oat_dex_files_.size()); 519 if (compiling_boot_image_) { 520 CHECK_EQ(image_writer_ != nullptr, 521 oat_header_->GetStoreValueByKey(OatHeader::kImageLocationKey) == nullptr); 522 } 523 524 write_state_ = WriteState::kWriteRoData; 525 } 526 527 OatWriter::~OatWriter() { 528 } 529 530 class OatWriter::DexMethodVisitor { 531 public: 532 DexMethodVisitor(OatWriter* writer, size_t offset) 533 : writer_(writer), 534 offset_(offset), 535 dex_file_(nullptr), 536 class_def_index_(DexFile::kDexNoIndex) { 537 } 538 539 virtual bool StartClass(const DexFile* dex_file, size_t class_def_index) { 540 DCHECK(dex_file_ == nullptr); 541 DCHECK_EQ(class_def_index_, DexFile::kDexNoIndex); 542 dex_file_ = dex_file; 543 class_def_index_ = class_def_index; 544 return true; 545 } 546 547 virtual bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) = 0; 548 549 virtual bool EndClass() { 550 if (kIsDebugBuild) { 551 dex_file_ = nullptr; 552 class_def_index_ = DexFile::kDexNoIndex; 553 } 554 return true; 555 } 556 557 size_t GetOffset() const { 558 return offset_; 559 } 560 561 protected: 562 virtual ~DexMethodVisitor() { } 563 564 OatWriter* const writer_; 565 566 // The offset is usually advanced for each visited method by the derived class. 567 size_t offset_; 568 569 // The dex file and class def index are set in StartClass(). 570 const DexFile* dex_file_; 571 size_t class_def_index_; 572 }; 573 574 class OatWriter::OatDexMethodVisitor : public DexMethodVisitor { 575 public: 576 OatDexMethodVisitor(OatWriter* writer, size_t offset) 577 : DexMethodVisitor(writer, offset), 578 oat_class_index_(0u), 579 method_offsets_index_(0u) { 580 } 581 582 bool StartClass(const DexFile* dex_file, size_t class_def_index) { 583 DexMethodVisitor::StartClass(dex_file, class_def_index); 584 DCHECK_LT(oat_class_index_, writer_->oat_classes_.size()); 585 method_offsets_index_ = 0u; 586 return true; 587 } 588 589 bool EndClass() { 590 ++oat_class_index_; 591 return DexMethodVisitor::EndClass(); 592 } 593 594 protected: 595 size_t oat_class_index_; 596 size_t method_offsets_index_; 597 }; 598 599 class OatWriter::InitOatClassesMethodVisitor : public DexMethodVisitor { 600 public: 601 InitOatClassesMethodVisitor(OatWriter* writer, size_t offset) 602 : DexMethodVisitor(writer, offset), 603 compiled_methods_(), 604 num_non_null_compiled_methods_(0u) { 605 size_t num_classes = 0u; 606 for (const OatDexFile& oat_dex_file : writer_->oat_dex_files_) { 607 num_classes += oat_dex_file.class_offsets_.size(); 608 } 609 writer_->oat_classes_.reserve(num_classes); 610 compiled_methods_.reserve(256u); 611 } 612 613 bool StartClass(const DexFile* dex_file, size_t class_def_index) { 614 DexMethodVisitor::StartClass(dex_file, class_def_index); 615 compiled_methods_.clear(); 616 num_non_null_compiled_methods_ = 0u; 617 return true; 618 } 619 620 bool VisitMethod(size_t class_def_method_index ATTRIBUTE_UNUSED, 621 const ClassDataItemIterator& it) { 622 // Fill in the compiled_methods_ array for methods that have a 623 // CompiledMethod. We track the number of non-null entries in 624 // num_non_null_compiled_methods_ since we only want to allocate 625 // OatMethodOffsets for the compiled methods. 626 uint32_t method_idx = it.GetMemberIndex(); 627 CompiledMethod* compiled_method = 628 writer_->compiler_driver_->GetCompiledMethod(MethodReference(dex_file_, method_idx)); 629 compiled_methods_.push_back(compiled_method); 630 if (compiled_method != nullptr) { 631 ++num_non_null_compiled_methods_; 632 } 633 return true; 634 } 635 636 bool EndClass() { 637 ClassReference class_ref(dex_file_, class_def_index_); 638 CompiledClass* compiled_class = writer_->compiler_driver_->GetCompiledClass(class_ref); 639 mirror::Class::Status status; 640 if (compiled_class != nullptr) { 641 status = compiled_class->GetStatus(); 642 } else if (writer_->compiler_driver_->GetVerificationResults()->IsClassRejected(class_ref)) { 643 status = mirror::Class::kStatusError; 644 } else { 645 status = mirror::Class::kStatusNotReady; 646 } 647 648 writer_->oat_classes_.emplace_back(offset_, 649 compiled_methods_, 650 num_non_null_compiled_methods_, 651 status); 652 offset_ += writer_->oat_classes_.back().SizeOf(); 653 return DexMethodVisitor::EndClass(); 654 } 655 656 private: 657 dchecked_vector<CompiledMethod*> compiled_methods_; 658 size_t num_non_null_compiled_methods_; 659 }; 660 661 class OatWriter::InitCodeMethodVisitor : public OatDexMethodVisitor { 662 public: 663 InitCodeMethodVisitor(OatWriter* writer, size_t offset) 664 : OatDexMethodVisitor(writer, offset), 665 debuggable_(writer->GetCompilerDriver()->GetCompilerOptions().GetDebuggable()) { 666 writer_->absolute_patch_locations_.reserve( 667 writer_->compiler_driver_->GetNonRelativeLinkerPatchCount()); 668 } 669 670 bool EndClass() { 671 OatDexMethodVisitor::EndClass(); 672 if (oat_class_index_ == writer_->oat_classes_.size()) { 673 offset_ = writer_->relative_patcher_->ReserveSpaceEnd(offset_); 674 } 675 return true; 676 } 677 678 bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) 679 SHARED_REQUIRES(Locks::mutator_lock_) { 680 OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; 681 CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 682 683 if (compiled_method != nullptr) { 684 // Derived from CompiledMethod. 685 uint32_t quick_code_offset = 0; 686 687 ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode(); 688 uint32_t code_size = quick_code.size() * sizeof(uint8_t); 689 uint32_t thumb_offset = compiled_method->CodeDelta(); 690 691 // Deduplicate code arrays if we are not producing debuggable code. 692 bool deduped = true; 693 MethodReference method_ref(dex_file_, it.GetMemberIndex()); 694 if (debuggable_) { 695 quick_code_offset = writer_->relative_patcher_->GetOffset(method_ref); 696 if (quick_code_offset != 0u) { 697 // Duplicate methods, we want the same code for both of them so that the oat writer puts 698 // the same code in both ArtMethods so that we do not get different oat code at runtime. 699 } else { 700 quick_code_offset = NewQuickCodeOffset(compiled_method, it, thumb_offset); 701 deduped = false; 702 } 703 } else { 704 quick_code_offset = dedupe_map_.GetOrCreate( 705 compiled_method, 706 [this, &deduped, compiled_method, &it, thumb_offset]() { 707 deduped = false; 708 return NewQuickCodeOffset(compiled_method, it, thumb_offset); 709 }); 710 } 711 712 if (code_size != 0) { 713 if (writer_->relative_patcher_->GetOffset(method_ref) != 0u) { 714 // TODO: Should this be a hard failure? 715 LOG(WARNING) << "Multiple definitions of " 716 << PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file) 717 << " offsets " << writer_->relative_patcher_->GetOffset(method_ref) 718 << " " << quick_code_offset; 719 } else { 720 writer_->relative_patcher_->SetOffset(method_ref, quick_code_offset); 721 } 722 } 723 724 // Update quick method header. 725 DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size()); 726 OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_]; 727 uint32_t vmap_table_offset = method_header->vmap_table_offset_; 728 // If we don't have quick code, then we must have a vmap, as that is how the dex2dex 729 // compiler records its transformations. 730 DCHECK(!quick_code.empty() || vmap_table_offset != 0); 731 // The code offset was 0 when the mapping/vmap table offset was set, so it's set 732 // to 0-offset and we need to adjust it by code_offset. 733 uint32_t code_offset = quick_code_offset - thumb_offset; 734 if (vmap_table_offset != 0u && code_offset != 0u) { 735 vmap_table_offset += code_offset; 736 DCHECK_LT(vmap_table_offset, code_offset) << "Overflow in oat offsets"; 737 } 738 uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 739 uint32_t core_spill_mask = compiled_method->GetCoreSpillMask(); 740 uint32_t fp_spill_mask = compiled_method->GetFpSpillMask(); 741 *method_header = OatQuickMethodHeader(vmap_table_offset, 742 frame_size_in_bytes, 743 core_spill_mask, 744 fp_spill_mask, 745 code_size); 746 747 if (!deduped) { 748 // Update offsets. (Checksum is updated when writing.) 749 offset_ += sizeof(*method_header); // Method header is prepended before code. 750 offset_ += code_size; 751 // Record absolute patch locations. 752 if (!compiled_method->GetPatches().empty()) { 753 uintptr_t base_loc = offset_ - code_size - writer_->oat_header_->GetExecutableOffset(); 754 for (const LinkerPatch& patch : compiled_method->GetPatches()) { 755 if (!patch.IsPcRelative()) { 756 writer_->absolute_patch_locations_.push_back(base_loc + patch.LiteralOffset()); 757 } 758 } 759 } 760 } 761 762 const CompilerOptions& compiler_options = writer_->compiler_driver_->GetCompilerOptions(); 763 // Exclude quickened dex methods (code_size == 0) since they have no native code. 764 if (compiler_options.GenerateAnyDebugInfo() && code_size != 0) { 765 bool has_code_info = method_header->IsOptimized(); 766 // Record debug information for this function if we are doing that. 767 debug::MethodDebugInfo info = debug::MethodDebugInfo(); 768 info.trampoline_name = nullptr; 769 info.dex_file = dex_file_; 770 info.class_def_index = class_def_index_; 771 info.dex_method_index = it.GetMemberIndex(); 772 info.access_flags = it.GetMethodAccessFlags(); 773 info.code_item = it.GetMethodCodeItem(); 774 info.isa = compiled_method->GetInstructionSet(); 775 info.deduped = deduped; 776 info.is_native_debuggable = compiler_options.GetNativeDebuggable(); 777 info.is_optimized = method_header->IsOptimized(); 778 info.is_code_address_text_relative = true; 779 info.code_address = code_offset - writer_->oat_header_->GetExecutableOffset(); 780 info.code_size = code_size; 781 info.frame_size_in_bytes = compiled_method->GetFrameSizeInBytes(); 782 info.code_info = has_code_info ? compiled_method->GetVmapTable().data() : nullptr; 783 info.cfi = compiled_method->GetCFIInfo(); 784 writer_->method_info_.push_back(info); 785 } 786 787 DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); 788 OatMethodOffsets* offsets = &oat_class->method_offsets_[method_offsets_index_]; 789 offsets->code_offset_ = quick_code_offset; 790 ++method_offsets_index_; 791 } 792 793 return true; 794 } 795 796 private: 797 struct CodeOffsetsKeyComparator { 798 bool operator()(const CompiledMethod* lhs, const CompiledMethod* rhs) const { 799 // Code is deduplicated by CompilerDriver, compare only data pointers. 800 if (lhs->GetQuickCode().data() != rhs->GetQuickCode().data()) { 801 return lhs->GetQuickCode().data() < rhs->GetQuickCode().data(); 802 } 803 // If the code is the same, all other fields are likely to be the same as well. 804 if (UNLIKELY(lhs->GetVmapTable().data() != rhs->GetVmapTable().data())) { 805 return lhs->GetVmapTable().data() < rhs->GetVmapTable().data(); 806 } 807 if (UNLIKELY(lhs->GetPatches().data() != rhs->GetPatches().data())) { 808 return lhs->GetPatches().data() < rhs->GetPatches().data(); 809 } 810 return false; 811 } 812 }; 813 814 uint32_t NewQuickCodeOffset(CompiledMethod* compiled_method, 815 const ClassDataItemIterator& it, 816 uint32_t thumb_offset) { 817 offset_ = writer_->relative_patcher_->ReserveSpace( 818 offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex())); 819 offset_ = compiled_method->AlignCode(offset_); 820 DCHECK_ALIGNED_PARAM(offset_, 821 GetInstructionSetAlignment(compiled_method->GetInstructionSet())); 822 return offset_ + sizeof(OatQuickMethodHeader) + thumb_offset; 823 } 824 825 // Deduplication is already done on a pointer basis by the compiler driver, 826 // so we can simply compare the pointers to find out if things are duplicated. 827 SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_; 828 829 // Cache of compiler's --debuggable option. 830 const bool debuggable_; 831 }; 832 833 class OatWriter::InitMapMethodVisitor : public OatDexMethodVisitor { 834 public: 835 InitMapMethodVisitor(OatWriter* writer, size_t offset) 836 : OatDexMethodVisitor(writer, offset) { 837 } 838 839 bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it ATTRIBUTE_UNUSED) 840 SHARED_REQUIRES(Locks::mutator_lock_) { 841 OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; 842 CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 843 844 if (compiled_method != nullptr) { 845 DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); 846 DCHECK_EQ(oat_class->method_headers_[method_offsets_index_].vmap_table_offset_, 0u); 847 848 ArrayRef<const uint8_t> map = compiled_method->GetVmapTable(); 849 uint32_t map_size = map.size() * sizeof(map[0]); 850 if (map_size != 0u) { 851 size_t offset = dedupe_map_.GetOrCreate( 852 map.data(), 853 [this, map_size]() { 854 uint32_t new_offset = offset_; 855 offset_ += map_size; 856 return new_offset; 857 }); 858 // Code offset is not initialized yet, so set the map offset to 0u-offset. 859 DCHECK_EQ(oat_class->method_offsets_[method_offsets_index_].code_offset_, 0u); 860 oat_class->method_headers_[method_offsets_index_].vmap_table_offset_ = 0u - offset; 861 } 862 ++method_offsets_index_; 863 } 864 865 return true; 866 } 867 868 private: 869 // Deduplication is already done on a pointer basis by the compiler driver, 870 // so we can simply compare the pointers to find out if things are duplicated. 871 SafeMap<const uint8_t*, uint32_t> dedupe_map_; 872 }; 873 874 class OatWriter::InitImageMethodVisitor : public OatDexMethodVisitor { 875 public: 876 InitImageMethodVisitor(OatWriter* writer, size_t offset) 877 : OatDexMethodVisitor(writer, offset), 878 pointer_size_(GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet())) { 879 } 880 881 bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) 882 SHARED_REQUIRES(Locks::mutator_lock_) { 883 const DexFile::TypeId& type_id = 884 dex_file_->GetTypeId(dex_file_->GetClassDef(class_def_index_).class_idx_); 885 const char* class_descriptor = dex_file_->GetTypeDescriptor(type_id); 886 // Skip methods that are not in the image. 887 if (!writer_->GetCompilerDriver()->IsImageClass(class_descriptor)) { 888 return true; 889 } 890 891 OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; 892 CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 893 894 OatMethodOffsets offsets(0u); 895 if (compiled_method != nullptr) { 896 DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size()); 897 offsets = oat_class->method_offsets_[method_offsets_index_]; 898 ++method_offsets_index_; 899 } 900 901 ClassLinker* linker = Runtime::Current()->GetClassLinker(); 902 // Unchecked as we hold mutator_lock_ on entry. 903 ScopedObjectAccessUnchecked soa(Thread::Current()); 904 StackHandleScope<1> hs(soa.Self()); 905 Handle<mirror::DexCache> dex_cache(hs.NewHandle(linker->FindDexCache( 906 Thread::Current(), *dex_file_))); 907 ArtMethod* method; 908 if (writer_->HasBootImage()) { 909 const InvokeType invoke_type = it.GetMethodInvokeType( 910 dex_file_->GetClassDef(class_def_index_)); 911 method = linker->ResolveMethod<ClassLinker::kNoICCECheckForCache>( 912 *dex_file_, 913 it.GetMemberIndex(), 914 dex_cache, 915 ScopedNullHandle<mirror::ClassLoader>(), 916 nullptr, 917 invoke_type); 918 if (method == nullptr) { 919 LOG(INTERNAL_FATAL) << "Unexpected failure to resolve a method: " 920 << PrettyMethod(it.GetMemberIndex(), *dex_file_, true); 921 soa.Self()->AssertPendingException(); 922 mirror::Throwable* exc = soa.Self()->GetException(); 923 std::string dump = exc->Dump(); 924 LOG(FATAL) << dump; 925 UNREACHABLE(); 926 } 927 } else { 928 // Should already have been resolved by the compiler, just peek into the dex cache. 929 // It may not be resolved if the class failed to verify, in this case, don't set the 930 // entrypoint. This is not fatal since the dex cache will contain a resolution method. 931 method = dex_cache->GetResolvedMethod(it.GetMemberIndex(), linker->GetImagePointerSize()); 932 } 933 if (method != nullptr && 934 compiled_method != nullptr && 935 compiled_method->GetQuickCode().size() != 0) { 936 method->SetEntryPointFromQuickCompiledCodePtrSize( 937 reinterpret_cast<void*>(offsets.code_offset_), pointer_size_); 938 } 939 940 return true; 941 } 942 943 protected: 944 const size_t pointer_size_; 945 }; 946 947 class OatWriter::WriteCodeMethodVisitor : public OatDexMethodVisitor { 948 public: 949 WriteCodeMethodVisitor(OatWriter* writer, OutputStream* out, const size_t file_offset, 950 size_t relative_offset) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) 951 : OatDexMethodVisitor(writer, relative_offset), 952 out_(out), 953 file_offset_(file_offset), 954 soa_(Thread::Current()), 955 no_thread_suspension_(soa_.Self(), "OatWriter patching"), 956 class_linker_(Runtime::Current()->GetClassLinker()), 957 dex_cache_(nullptr) { 958 patched_code_.reserve(16 * KB); 959 if (writer_->HasBootImage()) { 960 // If we're creating the image, the address space must be ready so that we can apply patches. 961 CHECK(writer_->image_writer_->IsImageAddressSpaceReady()); 962 } 963 } 964 965 ~WriteCodeMethodVisitor() UNLOCK_FUNCTION(Locks::mutator_lock_) { 966 } 967 968 bool StartClass(const DexFile* dex_file, size_t class_def_index) 969 SHARED_REQUIRES(Locks::mutator_lock_) { 970 OatDexMethodVisitor::StartClass(dex_file, class_def_index); 971 if (dex_cache_ == nullptr || dex_cache_->GetDexFile() != dex_file) { 972 dex_cache_ = class_linker_->FindDexCache(Thread::Current(), *dex_file); 973 DCHECK(dex_cache_ != nullptr); 974 } 975 return true; 976 } 977 978 bool EndClass() SHARED_REQUIRES(Locks::mutator_lock_) { 979 bool result = OatDexMethodVisitor::EndClass(); 980 if (oat_class_index_ == writer_->oat_classes_.size()) { 981 DCHECK(result); // OatDexMethodVisitor::EndClass() never fails. 982 offset_ = writer_->relative_patcher_->WriteThunks(out_, offset_); 983 if (UNLIKELY(offset_ == 0u)) { 984 PLOG(ERROR) << "Failed to write final relative call thunks"; 985 result = false; 986 } 987 } 988 return result; 989 } 990 991 bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) 992 SHARED_REQUIRES(Locks::mutator_lock_) { 993 OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; 994 const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 995 996 // No thread suspension since dex_cache_ that may get invalidated if that occurs. 997 ScopedAssertNoThreadSuspension tsc(Thread::Current(), __FUNCTION__); 998 if (compiled_method != nullptr) { // ie. not an abstract method 999 size_t file_offset = file_offset_; 1000 OutputStream* out = out_; 1001 1002 ArrayRef<const uint8_t> quick_code = compiled_method->GetQuickCode(); 1003 uint32_t code_size = quick_code.size() * sizeof(uint8_t); 1004 1005 // Deduplicate code arrays. 1006 const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_]; 1007 if (method_offsets.code_offset_ > offset_) { 1008 offset_ = writer_->relative_patcher_->WriteThunks(out, offset_); 1009 if (offset_ == 0u) { 1010 ReportWriteFailure("relative call thunk", it); 1011 return false; 1012 } 1013 uint32_t aligned_offset = compiled_method->AlignCode(offset_); 1014 uint32_t aligned_code_delta = aligned_offset - offset_; 1015 if (aligned_code_delta != 0) { 1016 if (!writer_->WriteCodeAlignment(out, aligned_code_delta)) { 1017 ReportWriteFailure("code alignment padding", it); 1018 return false; 1019 } 1020 offset_ += aligned_code_delta; 1021 DCHECK_OFFSET_(); 1022 } 1023 DCHECK_ALIGNED_PARAM(offset_, 1024 GetInstructionSetAlignment(compiled_method->GetInstructionSet())); 1025 DCHECK_EQ(method_offsets.code_offset_, 1026 offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta()) 1027 << PrettyMethod(it.GetMemberIndex(), *dex_file_); 1028 const OatQuickMethodHeader& method_header = 1029 oat_class->method_headers_[method_offsets_index_]; 1030 if (!out->WriteFully(&method_header, sizeof(method_header))) { 1031 ReportWriteFailure("method header", it); 1032 return false; 1033 } 1034 writer_->size_method_header_ += sizeof(method_header); 1035 offset_ += sizeof(method_header); 1036 DCHECK_OFFSET_(); 1037 1038 if (!compiled_method->GetPatches().empty()) { 1039 patched_code_.assign(quick_code.begin(), quick_code.end()); 1040 quick_code = ArrayRef<const uint8_t>(patched_code_); 1041 for (const LinkerPatch& patch : compiled_method->GetPatches()) { 1042 uint32_t literal_offset = patch.LiteralOffset(); 1043 switch (patch.GetType()) { 1044 case LinkerPatch::Type::kCallRelative: { 1045 // NOTE: Relative calls across oat files are not supported. 1046 uint32_t target_offset = GetTargetOffset(patch); 1047 writer_->relative_patcher_->PatchCall(&patched_code_, 1048 literal_offset, 1049 offset_ + literal_offset, 1050 target_offset); 1051 break; 1052 } 1053 case LinkerPatch::Type::kDexCacheArray: { 1054 uint32_t target_offset = GetDexCacheOffset(patch); 1055 writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, 1056 patch, 1057 offset_ + literal_offset, 1058 target_offset); 1059 break; 1060 } 1061 case LinkerPatch::Type::kStringRelative: { 1062 uint32_t target_offset = GetTargetObjectOffset(GetTargetString(patch)); 1063 writer_->relative_patcher_->PatchPcRelativeReference(&patched_code_, 1064 patch, 1065 offset_ + literal_offset, 1066 target_offset); 1067 break; 1068 } 1069 case LinkerPatch::Type::kCall: { 1070 uint32_t target_offset = GetTargetOffset(patch); 1071 PatchCodeAddress(&patched_code_, literal_offset, target_offset); 1072 break; 1073 } 1074 case LinkerPatch::Type::kMethod: { 1075 ArtMethod* method = GetTargetMethod(patch); 1076 PatchMethodAddress(&patched_code_, literal_offset, method); 1077 break; 1078 } 1079 case LinkerPatch::Type::kString: { 1080 mirror::String* string = GetTargetString(patch); 1081 PatchObjectAddress(&patched_code_, literal_offset, string); 1082 break; 1083 } 1084 case LinkerPatch::Type::kType: { 1085 mirror::Class* type = GetTargetType(patch); 1086 PatchObjectAddress(&patched_code_, literal_offset, type); 1087 break; 1088 } 1089 default: { 1090 DCHECK_EQ(patch.GetType(), LinkerPatch::Type::kRecordPosition); 1091 break; 1092 } 1093 } 1094 } 1095 } 1096 1097 if (!out->WriteFully(quick_code.data(), code_size)) { 1098 ReportWriteFailure("method code", it); 1099 return false; 1100 } 1101 writer_->size_code_ += code_size; 1102 offset_ += code_size; 1103 } 1104 DCHECK_OFFSET_(); 1105 ++method_offsets_index_; 1106 } 1107 1108 return true; 1109 } 1110 1111 private: 1112 OutputStream* const out_; 1113 const size_t file_offset_; 1114 const ScopedObjectAccess soa_; 1115 const ScopedAssertNoThreadSuspension no_thread_suspension_; 1116 ClassLinker* const class_linker_; 1117 mirror::DexCache* dex_cache_; 1118 std::vector<uint8_t> patched_code_; 1119 1120 void ReportWriteFailure(const char* what, const ClassDataItemIterator& it) { 1121 PLOG(ERROR) << "Failed to write " << what << " for " 1122 << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " to " << out_->GetLocation(); 1123 } 1124 1125 ArtMethod* GetTargetMethod(const LinkerPatch& patch) 1126 SHARED_REQUIRES(Locks::mutator_lock_) { 1127 MethodReference ref = patch.TargetMethod(); 1128 mirror::DexCache* dex_cache = 1129 (dex_file_ == ref.dex_file) ? dex_cache_ : class_linker_->FindDexCache( 1130 Thread::Current(), *ref.dex_file); 1131 ArtMethod* method = dex_cache->GetResolvedMethod( 1132 ref.dex_method_index, class_linker_->GetImagePointerSize()); 1133 CHECK(method != nullptr); 1134 return method; 1135 } 1136 1137 uint32_t GetTargetOffset(const LinkerPatch& patch) SHARED_REQUIRES(Locks::mutator_lock_) { 1138 uint32_t target_offset = writer_->relative_patcher_->GetOffset(patch.TargetMethod()); 1139 // If there's no new compiled code, either we're compiling an app and the target method 1140 // is in the boot image, or we need to point to the correct trampoline. 1141 if (UNLIKELY(target_offset == 0)) { 1142 ArtMethod* target = GetTargetMethod(patch); 1143 DCHECK(target != nullptr); 1144 size_t size = GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet()); 1145 const void* oat_code_offset = target->GetEntryPointFromQuickCompiledCodePtrSize(size); 1146 if (oat_code_offset != 0) { 1147 DCHECK(!writer_->HasBootImage()); 1148 DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickResolutionStub(oat_code_offset)); 1149 DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(oat_code_offset)); 1150 DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickGenericJniStub(oat_code_offset)); 1151 target_offset = PointerToLowMemUInt32(oat_code_offset); 1152 } else { 1153 target_offset = target->IsNative() 1154 ? writer_->oat_header_->GetQuickGenericJniTrampolineOffset() 1155 : writer_->oat_header_->GetQuickToInterpreterBridgeOffset(); 1156 } 1157 } 1158 return target_offset; 1159 } 1160 1161 mirror::Class* GetTargetType(const LinkerPatch& patch) SHARED_REQUIRES(Locks::mutator_lock_) { 1162 mirror::DexCache* dex_cache = (dex_file_ == patch.TargetTypeDexFile()) 1163 ? dex_cache_ 1164 : class_linker_->FindDexCache(Thread::Current(), *patch.TargetTypeDexFile()); 1165 mirror::Class* type = dex_cache->GetResolvedType(patch.TargetTypeIndex()); 1166 CHECK(type != nullptr); 1167 return type; 1168 } 1169 1170 mirror::String* GetTargetString(const LinkerPatch& patch) SHARED_REQUIRES(Locks::mutator_lock_) { 1171 mirror::String* string = dex_cache_->GetResolvedString(patch.TargetStringIndex()); 1172 DCHECK(string != nullptr); 1173 DCHECK(writer_->HasBootImage() || 1174 Runtime::Current()->GetHeap()->ObjectIsInBootImageSpace(string)); 1175 return string; 1176 } 1177 1178 uint32_t GetDexCacheOffset(const LinkerPatch& patch) SHARED_REQUIRES(Locks::mutator_lock_) { 1179 if (writer_->HasBootImage()) { 1180 uintptr_t element = writer_->image_writer_->GetDexCacheArrayElementImageAddress<uintptr_t>( 1181 patch.TargetDexCacheDexFile(), patch.TargetDexCacheElementOffset()); 1182 size_t oat_index = writer_->image_writer_->GetOatIndexForDexCache(dex_cache_); 1183 uintptr_t oat_data = writer_->image_writer_->GetOatDataBegin(oat_index); 1184 return element - oat_data; 1185 } else { 1186 size_t start = writer_->dex_cache_arrays_offsets_.Get(patch.TargetDexCacheDexFile()); 1187 return start + patch.TargetDexCacheElementOffset(); 1188 } 1189 } 1190 1191 uint32_t GetTargetObjectOffset(mirror::Object* object) SHARED_REQUIRES(Locks::mutator_lock_) { 1192 DCHECK(writer_->HasBootImage()); 1193 object = writer_->image_writer_->GetImageAddress(object); 1194 size_t oat_index = writer_->image_writer_->GetOatIndexForDexFile(dex_file_); 1195 uintptr_t oat_data_begin = writer_->image_writer_->GetOatDataBegin(oat_index); 1196 // TODO: Clean up offset types. The target offset must be treated as signed. 1197 return static_cast<uint32_t>(reinterpret_cast<uintptr_t>(object) - oat_data_begin); 1198 } 1199 1200 void PatchObjectAddress(std::vector<uint8_t>* code, uint32_t offset, mirror::Object* object) 1201 SHARED_REQUIRES(Locks::mutator_lock_) { 1202 if (writer_->HasBootImage()) { 1203 object = writer_->image_writer_->GetImageAddress(object); 1204 } else { 1205 // NOTE: We're using linker patches for app->boot references when the image can 1206 // be relocated and therefore we need to emit .oat_patches. We're not using this 1207 // for app->app references, so check that the object is in the image space. 1208 DCHECK(Runtime::Current()->GetHeap()->FindSpaceFromObject(object, false)->IsImageSpace()); 1209 } 1210 // Note: We only patch targeting Objects in image which is in the low 4gb. 1211 uint32_t address = PointerToLowMemUInt32(object); 1212 DCHECK_LE(offset + 4, code->size()); 1213 uint8_t* data = &(*code)[offset]; 1214 data[0] = address & 0xffu; 1215 data[1] = (address >> 8) & 0xffu; 1216 data[2] = (address >> 16) & 0xffu; 1217 data[3] = (address >> 24) & 0xffu; 1218 } 1219 1220 void PatchMethodAddress(std::vector<uint8_t>* code, uint32_t offset, ArtMethod* method) 1221 SHARED_REQUIRES(Locks::mutator_lock_) { 1222 if (writer_->HasBootImage()) { 1223 method = writer_->image_writer_->GetImageMethodAddress(method); 1224 } else if (kIsDebugBuild) { 1225 // NOTE: We're using linker patches for app->boot references when the image can 1226 // be relocated and therefore we need to emit .oat_patches. We're not using this 1227 // for app->app references, so check that the method is an image method. 1228 std::vector<gc::space::ImageSpace*> image_spaces = 1229 Runtime::Current()->GetHeap()->GetBootImageSpaces(); 1230 bool contains_method = false; 1231 for (gc::space::ImageSpace* image_space : image_spaces) { 1232 size_t method_offset = reinterpret_cast<const uint8_t*>(method) - image_space->Begin(); 1233 contains_method |= 1234 image_space->GetImageHeader().GetMethodsSection().Contains(method_offset); 1235 } 1236 CHECK(contains_method); 1237 } 1238 // Note: We only patch targeting ArtMethods in image which is in the low 4gb. 1239 uint32_t address = PointerToLowMemUInt32(method); 1240 DCHECK_LE(offset + 4, code->size()); 1241 uint8_t* data = &(*code)[offset]; 1242 data[0] = address & 0xffu; 1243 data[1] = (address >> 8) & 0xffu; 1244 data[2] = (address >> 16) & 0xffu; 1245 data[3] = (address >> 24) & 0xffu; 1246 } 1247 1248 void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset) 1249 SHARED_REQUIRES(Locks::mutator_lock_) { 1250 uint32_t address = target_offset; 1251 if (writer_->HasBootImage()) { 1252 size_t oat_index = writer_->image_writer_->GetOatIndexForDexCache(dex_cache_); 1253 // TODO: Clean up offset types. 1254 // The target_offset must be treated as signed for cross-oat patching. 1255 const void* target = reinterpret_cast<const void*>( 1256 writer_->image_writer_->GetOatDataBegin(oat_index) + 1257 static_cast<int32_t>(target_offset)); 1258 address = PointerToLowMemUInt32(target); 1259 } 1260 DCHECK_LE(offset + 4, code->size()); 1261 uint8_t* data = &(*code)[offset]; 1262 data[0] = address & 0xffu; 1263 data[1] = (address >> 8) & 0xffu; 1264 data[2] = (address >> 16) & 0xffu; 1265 data[3] = (address >> 24) & 0xffu; 1266 } 1267 }; 1268 1269 class OatWriter::WriteMapMethodVisitor : public OatDexMethodVisitor { 1270 public: 1271 WriteMapMethodVisitor(OatWriter* writer, 1272 OutputStream* out, 1273 const size_t file_offset, 1274 size_t relative_offset) 1275 : OatDexMethodVisitor(writer, relative_offset), 1276 out_(out), 1277 file_offset_(file_offset) { 1278 } 1279 1280 bool VisitMethod(size_t class_def_method_index, const ClassDataItemIterator& it) { 1281 OatClass* oat_class = &writer_->oat_classes_[oat_class_index_]; 1282 const CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index); 1283 1284 if (compiled_method != nullptr) { // ie. not an abstract method 1285 size_t file_offset = file_offset_; 1286 OutputStream* out = out_; 1287 1288 uint32_t map_offset = oat_class->method_headers_[method_offsets_index_].vmap_table_offset_; 1289 uint32_t code_offset = oat_class->method_offsets_[method_offsets_index_].code_offset_; 1290 ++method_offsets_index_; 1291 1292 DCHECK((compiled_method->GetVmapTable().size() == 0u && map_offset == 0u) || 1293 (compiled_method->GetVmapTable().size() != 0u && map_offset != 0u)) 1294 << compiled_method->GetVmapTable().size() << " " << map_offset << " " 1295 << PrettyMethod(it.GetMemberIndex(), *dex_file_); 1296 1297 if (map_offset != 0u) { 1298 // Transform map_offset to actual oat data offset. 1299 map_offset = (code_offset - compiled_method->CodeDelta()) - map_offset; 1300 DCHECK_NE(map_offset, 0u); 1301 DCHECK_LE(map_offset, offset_) << PrettyMethod(it.GetMemberIndex(), *dex_file_); 1302 1303 ArrayRef<const uint8_t> map = compiled_method->GetVmapTable(); 1304 size_t map_size = map.size() * sizeof(map[0]); 1305 if (map_offset == offset_) { 1306 // Write deduplicated map (code info for Optimizing or transformation info for dex2dex). 1307 if (UNLIKELY(!out->WriteFully(map.data(), map_size))) { 1308 ReportWriteFailure(it); 1309 return false; 1310 } 1311 offset_ += map_size; 1312 } 1313 } 1314 DCHECK_OFFSET_(); 1315 } 1316 1317 return true; 1318 } 1319 1320 private: 1321 OutputStream* const out_; 1322 size_t const file_offset_; 1323 1324 void ReportWriteFailure(const ClassDataItemIterator& it) { 1325 PLOG(ERROR) << "Failed to write map for " 1326 << PrettyMethod(it.GetMemberIndex(), *dex_file_) << " to " << out_->GetLocation(); 1327 } 1328 }; 1329 1330 // Visit all methods from all classes in all dex files with the specified visitor. 1331 bool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) { 1332 for (const DexFile* dex_file : *dex_files_) { 1333 const size_t class_def_count = dex_file->NumClassDefs(); 1334 for (size_t class_def_index = 0; class_def_index != class_def_count; ++class_def_index) { 1335 if (UNLIKELY(!visitor->StartClass(dex_file, class_def_index))) { 1336 return false; 1337 } 1338 const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index); 1339 const uint8_t* class_data = dex_file->GetClassData(class_def); 1340 if (class_data != nullptr) { // ie not an empty class, such as a marker interface 1341 ClassDataItemIterator it(*dex_file, class_data); 1342 while (it.HasNextStaticField()) { 1343 it.Next(); 1344 } 1345 while (it.HasNextInstanceField()) { 1346 it.Next(); 1347 } 1348 size_t class_def_method_index = 0u; 1349 while (it.HasNextDirectMethod()) { 1350 if (!visitor->VisitMethod(class_def_method_index, it)) { 1351 return false; 1352 } 1353 ++class_def_method_index; 1354 it.Next(); 1355 } 1356 while (it.HasNextVirtualMethod()) { 1357 if (UNLIKELY(!visitor->VisitMethod(class_def_method_index, it))) { 1358 return false; 1359 } 1360 ++class_def_method_index; 1361 it.Next(); 1362 } 1363 } 1364 if (UNLIKELY(!visitor->EndClass())) { 1365 return false; 1366 } 1367 } 1368 } 1369 return true; 1370 } 1371 1372 size_t OatWriter::InitOatHeader(InstructionSet instruction_set, 1373 const InstructionSetFeatures* instruction_set_features, 1374 uint32_t num_dex_files, 1375 SafeMap<std::string, std::string>* key_value_store) { 1376 TimingLogger::ScopedTiming split("InitOatHeader", timings_); 1377 oat_header_.reset(OatHeader::Create(instruction_set, 1378 instruction_set_features, 1379 num_dex_files, 1380 key_value_store)); 1381 size_oat_header_ += sizeof(OatHeader); 1382 size_oat_header_key_value_store_ += oat_header_->GetHeaderSize() - sizeof(OatHeader); 1383 return oat_header_->GetHeaderSize(); 1384 } 1385 1386 size_t OatWriter::InitOatDexFiles(size_t offset) { 1387 TimingLogger::ScopedTiming split("InitOatDexFiles", timings_); 1388 // Initialize offsets of dex files. 1389 for (OatDexFile& oat_dex_file : oat_dex_files_) { 1390 oat_dex_file.offset_ = offset; 1391 offset += oat_dex_file.SizeOf(); 1392 } 1393 return offset; 1394 } 1395 1396 size_t OatWriter::InitOatClasses(size_t offset) { 1397 // calculate the offsets within OatDexFiles to OatClasses 1398 InitOatClassesMethodVisitor visitor(this, offset); 1399 bool success = VisitDexMethods(&visitor); 1400 CHECK(success); 1401 offset = visitor.GetOffset(); 1402 1403 // Update oat_dex_files_. 1404 auto oat_class_it = oat_classes_.begin(); 1405 for (OatDexFile& oat_dex_file : oat_dex_files_) { 1406 for (uint32_t& class_offset : oat_dex_file.class_offsets_) { 1407 DCHECK(oat_class_it != oat_classes_.end()); 1408 class_offset = oat_class_it->offset_; 1409 ++oat_class_it; 1410 } 1411 } 1412 CHECK(oat_class_it == oat_classes_.end()); 1413 1414 return offset; 1415 } 1416 1417 size_t OatWriter::InitOatMaps(size_t offset) { 1418 InitMapMethodVisitor visitor(this, offset); 1419 bool success = VisitDexMethods(&visitor); 1420 DCHECK(success); 1421 offset = visitor.GetOffset(); 1422 1423 return offset; 1424 } 1425 1426 size_t OatWriter::InitOatCode(size_t offset) { 1427 // calculate the offsets within OatHeader to executable code 1428 size_t old_offset = offset; 1429 size_t adjusted_offset = offset; 1430 // required to be on a new page boundary 1431 offset = RoundUp(offset, kPageSize); 1432 oat_header_->SetExecutableOffset(offset); 1433 size_executable_offset_alignment_ = offset - old_offset; 1434 if (compiler_driver_->IsBootImage()) { 1435 InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); 1436 1437 #define DO_TRAMPOLINE(field, fn_name) \ 1438 offset = CompiledCode::AlignCode(offset, instruction_set); \ 1439 adjusted_offset = offset + CompiledCode::CodeDelta(instruction_set); \ 1440 oat_header_->Set ## fn_name ## Offset(adjusted_offset); \ 1441 field = compiler_driver_->Create ## fn_name(); \ 1442 offset += field->size(); 1443 1444 DO_TRAMPOLINE(jni_dlsym_lookup_, JniDlsymLookup); 1445 DO_TRAMPOLINE(quick_generic_jni_trampoline_, QuickGenericJniTrampoline); 1446 DO_TRAMPOLINE(quick_imt_conflict_trampoline_, QuickImtConflictTrampoline); 1447 DO_TRAMPOLINE(quick_resolution_trampoline_, QuickResolutionTrampoline); 1448 DO_TRAMPOLINE(quick_to_interpreter_bridge_, QuickToInterpreterBridge); 1449 1450 #undef DO_TRAMPOLINE 1451 } else { 1452 oat_header_->SetInterpreterToInterpreterBridgeOffset(0); 1453 oat_header_->SetInterpreterToCompiledCodeBridgeOffset(0); 1454 oat_header_->SetJniDlsymLookupOffset(0); 1455 oat_header_->SetQuickGenericJniTrampolineOffset(0); 1456 oat_header_->SetQuickImtConflictTrampolineOffset(0); 1457 oat_header_->SetQuickResolutionTrampolineOffset(0); 1458 oat_header_->SetQuickToInterpreterBridgeOffset(0); 1459 } 1460 return offset; 1461 } 1462 1463 size_t OatWriter::InitOatCodeDexFiles(size_t offset) { 1464 #define VISIT(VisitorType) \ 1465 do { \ 1466 VisitorType visitor(this, offset); \ 1467 bool success = VisitDexMethods(&visitor); \ 1468 DCHECK(success); \ 1469 offset = visitor.GetOffset(); \ 1470 } while (false) 1471 1472 VISIT(InitCodeMethodVisitor); 1473 if (HasImage()) { 1474 VISIT(InitImageMethodVisitor); 1475 } 1476 1477 #undef VISIT 1478 1479 return offset; 1480 } 1481 1482 bool OatWriter::WriteRodata(OutputStream* out) { 1483 CHECK(write_state_ == WriteState::kWriteRoData); 1484 1485 // Wrap out to update checksum with each write. 1486 ChecksumUpdatingOutputStream checksum_updating_out(out, oat_header_.get()); 1487 out = &checksum_updating_out; 1488 1489 if (!WriteClassOffsets(out)) { 1490 LOG(ERROR) << "Failed to write class offsets to " << out->GetLocation(); 1491 return false; 1492 } 1493 1494 if (!WriteClasses(out)) { 1495 LOG(ERROR) << "Failed to write classes to " << out->GetLocation(); 1496 return false; 1497 } 1498 1499 off_t tables_end_offset = out->Seek(0, kSeekCurrent); 1500 if (tables_end_offset == static_cast<off_t>(-1)) { 1501 LOG(ERROR) << "Failed to seek to oat code position in " << out->GetLocation(); 1502 return false; 1503 } 1504 size_t file_offset = oat_data_offset_; 1505 size_t relative_offset = static_cast<size_t>(tables_end_offset) - file_offset; 1506 relative_offset = WriteMaps(out, file_offset, relative_offset); 1507 if (relative_offset == 0) { 1508 LOG(ERROR) << "Failed to write oat code to " << out->GetLocation(); 1509 return false; 1510 } 1511 1512 // Write padding. 1513 off_t new_offset = out->Seek(size_executable_offset_alignment_, kSeekCurrent); 1514 relative_offset += size_executable_offset_alignment_; 1515 DCHECK_EQ(relative_offset, oat_header_->GetExecutableOffset()); 1516 size_t expected_file_offset = file_offset + relative_offset; 1517 if (static_cast<uint32_t>(new_offset) != expected_file_offset) { 1518 PLOG(ERROR) << "Failed to seek to oat code section. Actual: " << new_offset 1519 << " Expected: " << expected_file_offset << " File: " << out->GetLocation(); 1520 return 0; 1521 } 1522 DCHECK_OFFSET(); 1523 1524 write_state_ = WriteState::kWriteText; 1525 return true; 1526 } 1527 1528 bool OatWriter::WriteCode(OutputStream* out) { 1529 CHECK(write_state_ == WriteState::kWriteText); 1530 1531 // Wrap out to update checksum with each write. 1532 ChecksumUpdatingOutputStream checksum_updating_out(out, oat_header_.get()); 1533 out = &checksum_updating_out; 1534 1535 SetMultiOatRelativePatcherAdjustment(); 1536 1537 const size_t file_offset = oat_data_offset_; 1538 size_t relative_offset = oat_header_->GetExecutableOffset(); 1539 DCHECK_OFFSET(); 1540 1541 relative_offset = WriteCode(out, file_offset, relative_offset); 1542 if (relative_offset == 0) { 1543 LOG(ERROR) << "Failed to write oat code to " << out->GetLocation(); 1544 return false; 1545 } 1546 1547 relative_offset = WriteCodeDexFiles(out, file_offset, relative_offset); 1548 if (relative_offset == 0) { 1549 LOG(ERROR) << "Failed to write oat code for dex files to " << out->GetLocation(); 1550 return false; 1551 } 1552 1553 const off_t oat_end_file_offset = out->Seek(0, kSeekCurrent); 1554 if (oat_end_file_offset == static_cast<off_t>(-1)) { 1555 LOG(ERROR) << "Failed to get oat end file offset in " << out->GetLocation(); 1556 return false; 1557 } 1558 1559 if (kIsDebugBuild) { 1560 uint32_t size_total = 0; 1561 #define DO_STAT(x) \ 1562 VLOG(compiler) << #x "=" << PrettySize(x) << " (" << x << "B)"; \ 1563 size_total += x; 1564 1565 DO_STAT(size_dex_file_alignment_); 1566 DO_STAT(size_executable_offset_alignment_); 1567 DO_STAT(size_oat_header_); 1568 DO_STAT(size_oat_header_key_value_store_); 1569 DO_STAT(size_dex_file_); 1570 DO_STAT(size_interpreter_to_interpreter_bridge_); 1571 DO_STAT(size_interpreter_to_compiled_code_bridge_); 1572 DO_STAT(size_jni_dlsym_lookup_); 1573 DO_STAT(size_quick_generic_jni_trampoline_); 1574 DO_STAT(size_quick_imt_conflict_trampoline_); 1575 DO_STAT(size_quick_resolution_trampoline_); 1576 DO_STAT(size_quick_to_interpreter_bridge_); 1577 DO_STAT(size_trampoline_alignment_); 1578 DO_STAT(size_method_header_); 1579 DO_STAT(size_code_); 1580 DO_STAT(size_code_alignment_); 1581 DO_STAT(size_relative_call_thunks_); 1582 DO_STAT(size_misc_thunks_); 1583 DO_STAT(size_vmap_table_); 1584 DO_STAT(size_oat_dex_file_location_size_); 1585 DO_STAT(size_oat_dex_file_location_data_); 1586 DO_STAT(size_oat_dex_file_location_checksum_); 1587 DO_STAT(size_oat_dex_file_offset_); 1588 DO_STAT(size_oat_dex_file_class_offsets_offset_); 1589 DO_STAT(size_oat_dex_file_lookup_table_offset_); 1590 DO_STAT(size_oat_lookup_table_alignment_); 1591 DO_STAT(size_oat_lookup_table_); 1592 DO_STAT(size_oat_class_offsets_alignment_); 1593 DO_STAT(size_oat_class_offsets_); 1594 DO_STAT(size_oat_class_type_); 1595 DO_STAT(size_oat_class_status_); 1596 DO_STAT(size_oat_class_method_bitmaps_); 1597 DO_STAT(size_oat_class_method_offsets_); 1598 #undef DO_STAT 1599 1600 VLOG(compiler) << "size_total=" << PrettySize(size_total) << " (" << size_total << "B)"; \ 1601 CHECK_EQ(file_offset + size_total, static_cast<size_t>(oat_end_file_offset)); 1602 CHECK_EQ(size_, size_total); 1603 } 1604 1605 CHECK_EQ(file_offset + size_, static_cast<size_t>(oat_end_file_offset)); 1606 CHECK_EQ(size_, relative_offset); 1607 1608 write_state_ = WriteState::kWriteHeader; 1609 return true; 1610 } 1611 1612 bool OatWriter::WriteHeader(OutputStream* out, 1613 uint32_t image_file_location_oat_checksum, 1614 uintptr_t image_file_location_oat_begin, 1615 int32_t image_patch_delta) { 1616 CHECK(write_state_ == WriteState::kWriteHeader); 1617 1618 oat_header_->SetImageFileLocationOatChecksum(image_file_location_oat_checksum); 1619 oat_header_->SetImageFileLocationOatDataBegin(image_file_location_oat_begin); 1620 if (compiler_driver_->IsBootImage()) { 1621 CHECK_EQ(image_patch_delta, 0); 1622 CHECK_EQ(oat_header_->GetImagePatchDelta(), 0); 1623 } else { 1624 CHECK_ALIGNED(image_patch_delta, kPageSize); 1625 oat_header_->SetImagePatchDelta(image_patch_delta); 1626 } 1627 oat_header_->UpdateChecksumWithHeaderData(); 1628 1629 const size_t file_offset = oat_data_offset_; 1630 1631 off_t current_offset = out->Seek(0, kSeekCurrent); 1632 if (current_offset == static_cast<off_t>(-1)) { 1633 PLOG(ERROR) << "Failed to get current offset from " << out->GetLocation(); 1634 return false; 1635 } 1636 if (out->Seek(file_offset, kSeekSet) == static_cast<off_t>(-1)) { 1637 PLOG(ERROR) << "Failed to seek to oat header position in " << out->GetLocation(); 1638 return false; 1639 } 1640 DCHECK_EQ(file_offset, static_cast<size_t>(out->Seek(0, kSeekCurrent))); 1641 1642 // Flush all other data before writing the header. 1643 if (!out->Flush()) { 1644 PLOG(ERROR) << "Failed to flush before writing oat header to " << out->GetLocation(); 1645 return false; 1646 } 1647 // Write the header. 1648 size_t header_size = oat_header_->GetHeaderSize(); 1649 if (!out->WriteFully(oat_header_.get(), header_size)) { 1650 PLOG(ERROR) << "Failed to write oat header to " << out->GetLocation(); 1651 return false; 1652 } 1653 // Flush the header data. 1654 if (!out->Flush()) { 1655 PLOG(ERROR) << "Failed to flush after writing oat header to " << out->GetLocation(); 1656 return false; 1657 } 1658 1659 if (out->Seek(current_offset, kSeekSet) == static_cast<off_t>(-1)) { 1660 PLOG(ERROR) << "Failed to seek back after writing oat header to " << out->GetLocation(); 1661 return false; 1662 } 1663 DCHECK_EQ(current_offset, out->Seek(0, kSeekCurrent)); 1664 1665 write_state_ = WriteState::kDone; 1666 return true; 1667 } 1668 1669 bool OatWriter::WriteClassOffsets(OutputStream* out) { 1670 for (OatDexFile& oat_dex_file : oat_dex_files_) { 1671 if (oat_dex_file.class_offsets_offset_ != 0u) { 1672 uint32_t expected_offset = oat_data_offset_ + oat_dex_file.class_offsets_offset_; 1673 off_t actual_offset = out->Seek(expected_offset, kSeekSet); 1674 if (static_cast<uint32_t>(actual_offset) != expected_offset) { 1675 PLOG(ERROR) << "Failed to seek to oat class offsets section. Actual: " << actual_offset 1676 << " Expected: " << expected_offset << " File: " << oat_dex_file.GetLocation(); 1677 return false; 1678 } 1679 if (!oat_dex_file.WriteClassOffsets(this, out)) { 1680 return false; 1681 } 1682 } 1683 } 1684 return true; 1685 } 1686 1687 bool OatWriter::WriteClasses(OutputStream* out) { 1688 for (OatClass& oat_class : oat_classes_) { 1689 if (!oat_class.Write(this, out, oat_data_offset_)) { 1690 PLOG(ERROR) << "Failed to write oat methods information to " << out->GetLocation(); 1691 return false; 1692 } 1693 } 1694 return true; 1695 } 1696 1697 size_t OatWriter::WriteMaps(OutputStream* out, const size_t file_offset, size_t relative_offset) { 1698 size_t vmap_tables_offset = relative_offset; 1699 WriteMapMethodVisitor visitor(this, out, file_offset, relative_offset); 1700 if (UNLIKELY(!VisitDexMethods(&visitor))) { 1701 return 0; 1702 } 1703 relative_offset = visitor.GetOffset(); 1704 size_vmap_table_ = relative_offset - vmap_tables_offset; 1705 1706 return relative_offset; 1707 } 1708 1709 size_t OatWriter::WriteCode(OutputStream* out, const size_t file_offset, size_t relative_offset) { 1710 if (compiler_driver_->IsBootImage()) { 1711 InstructionSet instruction_set = compiler_driver_->GetInstructionSet(); 1712 1713 #define DO_TRAMPOLINE(field) \ 1714 do { \ 1715 uint32_t aligned_offset = CompiledCode::AlignCode(relative_offset, instruction_set); \ 1716 uint32_t alignment_padding = aligned_offset - relative_offset; \ 1717 out->Seek(alignment_padding, kSeekCurrent); \ 1718 size_trampoline_alignment_ += alignment_padding; \ 1719 if (!out->WriteFully(field->data(), field->size())) { \ 1720 PLOG(ERROR) << "Failed to write " # field " to " << out->GetLocation(); \ 1721 return false; \ 1722 } \ 1723 size_ ## field += field->size(); \ 1724 relative_offset += alignment_padding + field->size(); \ 1725 DCHECK_OFFSET(); \ 1726 } while (false) 1727 1728 DO_TRAMPOLINE(jni_dlsym_lookup_); 1729 DO_TRAMPOLINE(quick_generic_jni_trampoline_); 1730 DO_TRAMPOLINE(quick_imt_conflict_trampoline_); 1731 DO_TRAMPOLINE(quick_resolution_trampoline_); 1732 DO_TRAMPOLINE(quick_to_interpreter_bridge_); 1733 #undef DO_TRAMPOLINE 1734 } 1735 return relative_offset; 1736 } 1737 1738 size_t OatWriter::WriteCodeDexFiles(OutputStream* out, 1739 const size_t file_offset, 1740 size_t relative_offset) { 1741 #define VISIT(VisitorType) \ 1742 do { \ 1743 VisitorType visitor(this, out, file_offset, relative_offset); \ 1744 if (UNLIKELY(!VisitDexMethods(&visitor))) { \ 1745 return 0; \ 1746 } \ 1747 relative_offset = visitor.GetOffset(); \ 1748 } while (false) 1749 1750 VISIT(WriteCodeMethodVisitor); 1751 1752 #undef VISIT 1753 1754 size_code_alignment_ += relative_patcher_->CodeAlignmentSize(); 1755 size_relative_call_thunks_ += relative_patcher_->RelativeCallThunksSize(); 1756 size_misc_thunks_ += relative_patcher_->MiscThunksSize(); 1757 1758 return relative_offset; 1759 } 1760 1761 bool OatWriter::RecordOatDataOffset(OutputStream* out) { 1762 // Get the elf file offset of the oat file. 1763 const off_t raw_file_offset = out->Seek(0, kSeekCurrent); 1764 if (raw_file_offset == static_cast<off_t>(-1)) { 1765 LOG(ERROR) << "Failed to get file offset in " << out->GetLocation(); 1766 return false; 1767 } 1768 oat_data_offset_ = static_cast<size_t>(raw_file_offset); 1769 return true; 1770 } 1771 1772 bool OatWriter::ReadDexFileHeader(File* file, OatDexFile* oat_dex_file) { 1773 // Read the dex file header and perform minimal verification. 1774 uint8_t raw_header[sizeof(DexFile::Header)]; 1775 if (!file->ReadFully(&raw_header, sizeof(DexFile::Header))) { 1776 PLOG(ERROR) << "Failed to read dex file header. Actual: " 1777 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1778 return false; 1779 } 1780 if (!ValidateDexFileHeader(raw_header, oat_dex_file->GetLocation())) { 1781 return false; 1782 } 1783 1784 const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_header); 1785 oat_dex_file->dex_file_size_ = header->file_size_; 1786 oat_dex_file->dex_file_location_checksum_ = header->checksum_; 1787 oat_dex_file->class_offsets_.resize(header->class_defs_size_); 1788 return true; 1789 } 1790 1791 bool OatWriter::ValidateDexFileHeader(const uint8_t* raw_header, const char* location) { 1792 if (!DexFile::IsMagicValid(raw_header)) { 1793 LOG(ERROR) << "Invalid magic number in dex file header. " << " File: " << location; 1794 return false; 1795 } 1796 if (!DexFile::IsVersionValid(raw_header)) { 1797 LOG(ERROR) << "Invalid version number in dex file header. " << " File: " << location; 1798 return false; 1799 } 1800 const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_header); 1801 if (header->file_size_ < sizeof(DexFile::Header)) { 1802 LOG(ERROR) << "Dex file header specifies file size insufficient to contain the header." 1803 << " File: " << location; 1804 return false; 1805 } 1806 return true; 1807 } 1808 1809 bool OatWriter::WriteDexFiles(OutputStream* rodata, File* file) { 1810 TimingLogger::ScopedTiming split("WriteDexFiles", timings_); 1811 1812 // Get the elf file offset of the oat file. 1813 if (!RecordOatDataOffset(rodata)) { 1814 return false; 1815 } 1816 1817 // Write dex files. 1818 for (OatDexFile& oat_dex_file : oat_dex_files_) { 1819 if (!WriteDexFile(rodata, file, &oat_dex_file)) { 1820 return false; 1821 } 1822 } 1823 1824 // Close sources. 1825 for (OatDexFile& oat_dex_file : oat_dex_files_) { 1826 oat_dex_file.source_.Clear(); // Get rid of the reference, it's about to be invalidated. 1827 } 1828 zipped_dex_files_.clear(); 1829 zip_archives_.clear(); 1830 raw_dex_files_.clear(); 1831 return true; 1832 } 1833 1834 bool OatWriter::WriteDexFile(OutputStream* rodata, File* file, OatDexFile* oat_dex_file) { 1835 if (!SeekToDexFile(rodata, file, oat_dex_file)) { 1836 return false; 1837 } 1838 if (oat_dex_file->source_.IsZipEntry()) { 1839 if (!WriteDexFile(rodata, file, oat_dex_file, oat_dex_file->source_.GetZipEntry())) { 1840 return false; 1841 } 1842 } else if (oat_dex_file->source_.IsRawFile()) { 1843 if (!WriteDexFile(rodata, file, oat_dex_file, oat_dex_file->source_.GetRawFile())) { 1844 return false; 1845 } 1846 } else { 1847 DCHECK(oat_dex_file->source_.IsRawData()); 1848 if (!WriteDexFile(rodata, oat_dex_file, oat_dex_file->source_.GetRawData())) { 1849 return false; 1850 } 1851 } 1852 1853 // Update current size and account for the written data. 1854 DCHECK_EQ(size_, oat_dex_file->dex_file_offset_); 1855 size_ += oat_dex_file->dex_file_size_; 1856 size_dex_file_ += oat_dex_file->dex_file_size_; 1857 return true; 1858 } 1859 1860 bool OatWriter::SeekToDexFile(OutputStream* out, File* file, OatDexFile* oat_dex_file) { 1861 // Dex files are required to be 4 byte aligned. 1862 size_t original_offset = size_; 1863 size_t offset = RoundUp(original_offset, 4); 1864 size_dex_file_alignment_ += offset - original_offset; 1865 1866 // Seek to the start of the dex file and flush any pending operations in the stream. 1867 // Verify that, after flushing the stream, the file is at the same offset as the stream. 1868 uint32_t start_offset = oat_data_offset_ + offset; 1869 off_t actual_offset = out->Seek(start_offset, kSeekSet); 1870 if (actual_offset != static_cast<off_t>(start_offset)) { 1871 PLOG(ERROR) << "Failed to seek to dex file section. Actual: " << actual_offset 1872 << " Expected: " << start_offset 1873 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1874 return false; 1875 } 1876 if (!out->Flush()) { 1877 PLOG(ERROR) << "Failed to flush before writing dex file." 1878 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1879 return false; 1880 } 1881 actual_offset = lseek(file->Fd(), 0, SEEK_CUR); 1882 if (actual_offset != static_cast<off_t>(start_offset)) { 1883 PLOG(ERROR) << "Stream/file position mismatch! Actual: " << actual_offset 1884 << " Expected: " << start_offset 1885 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1886 return false; 1887 } 1888 1889 size_ = offset; 1890 oat_dex_file->dex_file_offset_ = offset; 1891 return true; 1892 } 1893 1894 bool OatWriter::WriteDexFile(OutputStream* rodata, 1895 File* file, 1896 OatDexFile* oat_dex_file, 1897 ZipEntry* dex_file) { 1898 size_t start_offset = oat_data_offset_ + size_; 1899 DCHECK_EQ(static_cast<off_t>(start_offset), rodata->Seek(0, kSeekCurrent)); 1900 1901 // Extract the dex file and get the extracted size. 1902 std::string error_msg; 1903 if (!dex_file->ExtractToFile(*file, &error_msg)) { 1904 LOG(ERROR) << "Failed to extract dex file from ZIP entry: " << error_msg 1905 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1906 return false; 1907 } 1908 if (file->Flush() != 0) { 1909 PLOG(ERROR) << "Failed to flush dex file from ZIP entry." 1910 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1911 return false; 1912 } 1913 off_t extracted_end = lseek(file->Fd(), 0, SEEK_CUR); 1914 if (extracted_end == static_cast<off_t>(-1)) { 1915 PLOG(ERROR) << "Failed get end offset after writing dex file from ZIP entry." 1916 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1917 return false; 1918 } 1919 if (extracted_end < static_cast<off_t>(start_offset)) { 1920 LOG(ERROR) << "Dex file end position is before start position! End: " << extracted_end 1921 << " Start: " << start_offset 1922 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1923 return false; 1924 } 1925 uint64_t extracted_size = static_cast<uint64_t>(extracted_end - start_offset); 1926 if (extracted_size < sizeof(DexFile::Header)) { 1927 LOG(ERROR) << "Extracted dex file is shorter than dex file header. size: " 1928 << extracted_size << " File: " << oat_dex_file->GetLocation(); 1929 return false; 1930 } 1931 1932 // Read the dex file header and extract required data to OatDexFile. 1933 off_t actual_offset = lseek(file->Fd(), start_offset, SEEK_SET); 1934 if (actual_offset != static_cast<off_t>(start_offset)) { 1935 PLOG(ERROR) << "Failed to seek back to dex file header. Actual: " << actual_offset 1936 << " Expected: " << start_offset 1937 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1938 return false; 1939 } 1940 if (!ReadDexFileHeader(file, oat_dex_file)) { 1941 return false; 1942 } 1943 if (extracted_size < oat_dex_file->dex_file_size_) { 1944 LOG(ERROR) << "Extracted truncated dex file. Extracted size: " << extracted_size 1945 << " file size from header: " << oat_dex_file->dex_file_size_ 1946 << " File: " << oat_dex_file->GetLocation(); 1947 return false; 1948 } 1949 1950 // Override the checksum from header with the CRC from ZIP entry. 1951 oat_dex_file->dex_file_location_checksum_ = dex_file->GetCrc32(); 1952 1953 // Seek both file and stream to the end offset. 1954 size_t end_offset = start_offset + oat_dex_file->dex_file_size_; 1955 actual_offset = lseek(file->Fd(), end_offset, SEEK_SET); 1956 if (actual_offset != static_cast<off_t>(end_offset)) { 1957 PLOG(ERROR) << "Failed to seek to end of dex file. Actual: " << actual_offset 1958 << " Expected: " << end_offset 1959 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1960 return false; 1961 } 1962 actual_offset = rodata->Seek(end_offset, kSeekSet); 1963 if (actual_offset != static_cast<off_t>(end_offset)) { 1964 PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset 1965 << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation(); 1966 return false; 1967 } 1968 if (!rodata->Flush()) { 1969 PLOG(ERROR) << "Failed to flush stream after seeking over dex file." 1970 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1971 return false; 1972 } 1973 1974 // If we extracted more than the size specified in the header, truncate the file. 1975 if (extracted_size > oat_dex_file->dex_file_size_) { 1976 if (file->SetLength(end_offset) != 0) { 1977 PLOG(ERROR) << "Failed to truncate excessive dex file length." 1978 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1979 return false; 1980 } 1981 } 1982 1983 return true; 1984 } 1985 1986 bool OatWriter::WriteDexFile(OutputStream* rodata, 1987 File* file, 1988 OatDexFile* oat_dex_file, 1989 File* dex_file) { 1990 size_t start_offset = oat_data_offset_ + size_; 1991 DCHECK_EQ(static_cast<off_t>(start_offset), rodata->Seek(0, kSeekCurrent)); 1992 1993 off_t input_offset = lseek(dex_file->Fd(), 0, SEEK_SET); 1994 if (input_offset != static_cast<off_t>(0)) { 1995 PLOG(ERROR) << "Failed to seek to dex file header. Actual: " << input_offset 1996 << " Expected: 0" 1997 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 1998 return false; 1999 } 2000 if (!ReadDexFileHeader(dex_file, oat_dex_file)) { 2001 return false; 2002 } 2003 2004 // Copy the input dex file using sendfile(). 2005 if (!file->Copy(dex_file, 0, oat_dex_file->dex_file_size_)) { 2006 PLOG(ERROR) << "Failed to copy dex file to oat file." 2007 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 2008 return false; 2009 } 2010 if (file->Flush() != 0) { 2011 PLOG(ERROR) << "Failed to flush dex file." 2012 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 2013 return false; 2014 } 2015 2016 // Check file position and seek the stream to the end offset. 2017 size_t end_offset = start_offset + oat_dex_file->dex_file_size_; 2018 off_t actual_offset = lseek(file->Fd(), 0, SEEK_CUR); 2019 if (actual_offset != static_cast<off_t>(end_offset)) { 2020 PLOG(ERROR) << "Unexpected file position after copying dex file. Actual: " << actual_offset 2021 << " Expected: " << end_offset 2022 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 2023 return false; 2024 } 2025 actual_offset = rodata->Seek(end_offset, kSeekSet); 2026 if (actual_offset != static_cast<off_t>(end_offset)) { 2027 PLOG(ERROR) << "Failed to seek stream to end of dex file. Actual: " << actual_offset 2028 << " Expected: " << end_offset << " File: " << oat_dex_file->GetLocation(); 2029 return false; 2030 } 2031 if (!rodata->Flush()) { 2032 PLOG(ERROR) << "Failed to flush stream after seeking over dex file." 2033 << " File: " << oat_dex_file->GetLocation() << " Output: " << file->GetPath(); 2034 return false; 2035 } 2036 2037 return true; 2038 } 2039 2040 bool OatWriter::WriteDexFile(OutputStream* rodata, 2041 OatDexFile* oat_dex_file, 2042 const uint8_t* dex_file) { 2043 // Note: The raw data has already been checked to contain the header 2044 // and all the data that the header specifies as the file size. 2045 DCHECK(dex_file != nullptr); 2046 DCHECK(ValidateDexFileHeader(dex_file, oat_dex_file->GetLocation())); 2047 const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(dex_file); 2048 2049 if (!rodata->WriteFully(dex_file, header->file_size_)) { 2050 PLOG(ERROR) << "Failed to write dex file " << oat_dex_file->GetLocation() 2051 << " to " << rodata->GetLocation(); 2052 return false; 2053 } 2054 if (!rodata->Flush()) { 2055 PLOG(ERROR) << "Failed to flush stream after writing dex file." 2056 << " File: " << oat_dex_file->GetLocation(); 2057 return false; 2058 } 2059 2060 // Update dex file size and resize class offsets in the OatDexFile. 2061 // Note: For raw data, the checksum is passed directly to AddRawDexFileSource(). 2062 oat_dex_file->dex_file_size_ = header->file_size_; 2063 oat_dex_file->class_offsets_.resize(header->class_defs_size_); 2064 return true; 2065 } 2066 2067 bool OatWriter::WriteOatDexFiles(OutputStream* rodata) { 2068 TimingLogger::ScopedTiming split("WriteOatDexFiles", timings_); 2069 2070 // Seek to the start of OatDexFiles, i.e. to the end of the OatHeader. If there are 2071 // no OatDexFiles, no data is actually written to .rodata before WriteHeader() and 2072 // this Seek() ensures that we reserve the space for OatHeader in .rodata. 2073 DCHECK(oat_dex_files_.empty() || oat_dex_files_[0u].offset_ == oat_header_->GetHeaderSize()); 2074 uint32_t expected_offset = oat_data_offset_ + oat_header_->GetHeaderSize(); 2075 off_t actual_offset = rodata->Seek(expected_offset, kSeekSet); 2076 if (static_cast<uint32_t>(actual_offset) != expected_offset) { 2077 PLOG(ERROR) << "Failed to seek to OatDexFile table section. Actual: " << actual_offset 2078 << " Expected: " << expected_offset << " File: " << rodata->GetLocation(); 2079 return false; 2080 } 2081 2082 for (size_t i = 0, size = oat_dex_files_.size(); i != size; ++i) { 2083 OatDexFile* oat_dex_file = &oat_dex_files_[i]; 2084 2085 DCHECK_EQ(oat_data_offset_ + oat_dex_file->offset_, 2086 static_cast<size_t>(rodata->Seek(0, kSeekCurrent))); 2087 2088 // Write OatDexFile. 2089 if (!oat_dex_file->Write(this, rodata)) { 2090 PLOG(ERROR) << "Failed to write oat dex information to " << rodata->GetLocation(); 2091 return false; 2092 } 2093 } 2094 2095 return true; 2096 } 2097 2098 bool OatWriter::ExtendForTypeLookupTables(OutputStream* rodata, File* file, size_t offset) { 2099 TimingLogger::ScopedTiming split("ExtendForTypeLookupTables", timings_); 2100 2101 int64_t new_length = oat_data_offset_ + dchecked_integral_cast<int64_t>(offset); 2102 if (file->SetLength(new_length) != 0) { 2103 PLOG(ERROR) << "Failed to extend file for type lookup tables. new_length: " << new_length 2104 << "File: " << file->GetPath(); 2105 return false; 2106 } 2107 off_t actual_offset = rodata->Seek(new_length, kSeekSet); 2108 if (actual_offset != static_cast<off_t>(new_length)) { 2109 PLOG(ERROR) << "Failed to seek stream after extending file for type lookup tables." 2110 << " Actual: " << actual_offset << " Expected: " << new_length 2111 << " File: " << rodata->GetLocation(); 2112 return false; 2113 } 2114 if (!rodata->Flush()) { 2115 PLOG(ERROR) << "Failed to flush stream after extending for type lookup tables." 2116 << " File: " << rodata->GetLocation(); 2117 return false; 2118 } 2119 return true; 2120 } 2121 2122 bool OatWriter::OpenDexFiles( 2123 File* file, 2124 bool verify, 2125 /*out*/ std::unique_ptr<MemMap>* opened_dex_files_map, 2126 /*out*/ std::vector<std::unique_ptr<const DexFile>>* opened_dex_files) { 2127 TimingLogger::ScopedTiming split("OpenDexFiles", timings_); 2128 2129 if (oat_dex_files_.empty()) { 2130 // Nothing to do. 2131 return true; 2132 } 2133 2134 size_t map_offset = oat_dex_files_[0].dex_file_offset_; 2135 size_t length = size_ - map_offset; 2136 std::string error_msg; 2137 std::unique_ptr<MemMap> dex_files_map(MemMap::MapFile(length, 2138 PROT_READ | PROT_WRITE, 2139 MAP_SHARED, 2140 file->Fd(), 2141 oat_data_offset_ + map_offset, 2142 /* low_4gb */ false, 2143 file->GetPath().c_str(), 2144 &error_msg)); 2145 if (dex_files_map == nullptr) { 2146 LOG(ERROR) << "Failed to mmap() dex files from oat file. File: " << file->GetPath() 2147 << " error: " << error_msg; 2148 return false; 2149 } 2150 std::vector<std::unique_ptr<const DexFile>> dex_files; 2151 for (OatDexFile& oat_dex_file : oat_dex_files_) { 2152 // Make sure no one messed with input files while we were copying data. 2153 // At the very least we need consistent file size and number of class definitions. 2154 const uint8_t* raw_dex_file = 2155 dex_files_map->Begin() + oat_dex_file.dex_file_offset_ - map_offset; 2156 if (!ValidateDexFileHeader(raw_dex_file, oat_dex_file.GetLocation())) { 2157 // Note: ValidateDexFileHeader() already logged an error message. 2158 LOG(ERROR) << "Failed to verify written dex file header!" 2159 << " Output: " << file->GetPath() << " ~ " << std::hex << map_offset 2160 << " ~ " << static_cast<const void*>(raw_dex_file); 2161 return false; 2162 } 2163 const UnalignedDexFileHeader* header = AsUnalignedDexFileHeader(raw_dex_file); 2164 if (header->file_size_ != oat_dex_file.dex_file_size_) { 2165 LOG(ERROR) << "File size mismatch in written dex file header! Expected: " 2166 << oat_dex_file.dex_file_size_ << " Actual: " << header->file_size_ 2167 << " Output: " << file->GetPath(); 2168 return false; 2169 } 2170 if (header->class_defs_size_ != oat_dex_file.class_offsets_.size()) { 2171 LOG(ERROR) << "Class defs size mismatch in written dex file header! Expected: " 2172 << oat_dex_file.class_offsets_.size() << " Actual: " << header->class_defs_size_ 2173 << " Output: " << file->GetPath(); 2174 return false; 2175 } 2176 2177 // Now, open the dex file. 2178 dex_files.emplace_back(DexFile::Open(raw_dex_file, 2179 oat_dex_file.dex_file_size_, 2180 oat_dex_file.GetLocation(), 2181 oat_dex_file.dex_file_location_checksum_, 2182 /* oat_dex_file */ nullptr, 2183 verify, 2184 &error_msg)); 2185 if (dex_files.back() == nullptr) { 2186 LOG(ERROR) << "Failed to open dex file from oat file. File: " << oat_dex_file.GetLocation() 2187 << " Error: " << error_msg; 2188 return false; 2189 } 2190 } 2191 2192 *opened_dex_files_map = std::move(dex_files_map); 2193 *opened_dex_files = std::move(dex_files); 2194 return true; 2195 } 2196 2197 bool OatWriter::WriteTypeLookupTables( 2198 MemMap* opened_dex_files_map, 2199 const std::vector<std::unique_ptr<const DexFile>>& opened_dex_files) { 2200 TimingLogger::ScopedTiming split("WriteTypeLookupTables", timings_); 2201 2202 DCHECK_EQ(opened_dex_files.size(), oat_dex_files_.size()); 2203 for (size_t i = 0, size = opened_dex_files.size(); i != size; ++i) { 2204 OatDexFile* oat_dex_file = &oat_dex_files_[i]; 2205 if (oat_dex_file->lookup_table_offset_ != 0u) { 2206 DCHECK(oat_dex_file->create_type_lookup_table_ == CreateTypeLookupTable::kCreate); 2207 DCHECK_NE(oat_dex_file->class_offsets_.size(), 0u); 2208 size_t map_offset = oat_dex_files_[0].dex_file_offset_; 2209 size_t lookup_table_offset = oat_dex_file->lookup_table_offset_; 2210 uint8_t* lookup_table = opened_dex_files_map->Begin() + (lookup_table_offset - map_offset); 2211 opened_dex_files[i]->CreateTypeLookupTable(lookup_table); 2212 } 2213 } 2214 2215 DCHECK_EQ(opened_dex_files_map == nullptr, opened_dex_files.empty()); 2216 if (opened_dex_files_map != nullptr && !opened_dex_files_map->Sync()) { 2217 PLOG(ERROR) << "Failed to Sync() type lookup tables. Map: " << opened_dex_files_map->GetName(); 2218 return false; 2219 } 2220 2221 return true; 2222 } 2223 2224 bool OatWriter::WriteCodeAlignment(OutputStream* out, uint32_t aligned_code_delta) { 2225 static const uint8_t kPadding[] = { 2226 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u 2227 }; 2228 DCHECK_LE(aligned_code_delta, sizeof(kPadding)); 2229 if (UNLIKELY(!out->WriteFully(kPadding, aligned_code_delta))) { 2230 return false; 2231 } 2232 size_code_alignment_ += aligned_code_delta; 2233 return true; 2234 } 2235 2236 void OatWriter::SetMultiOatRelativePatcherAdjustment() { 2237 DCHECK(dex_files_ != nullptr); 2238 DCHECK(relative_patcher_ != nullptr); 2239 DCHECK_NE(oat_data_offset_, 0u); 2240 if (image_writer_ != nullptr && !dex_files_->empty()) { 2241 // The oat data begin may not be initialized yet but the oat file offset is ready. 2242 size_t oat_index = image_writer_->GetOatIndexForDexFile(dex_files_->front()); 2243 size_t elf_file_offset = image_writer_->GetOatFileOffset(oat_index); 2244 relative_patcher_->StartOatFile(elf_file_offset + oat_data_offset_); 2245 } 2246 } 2247 2248 OatWriter::OatDexFile::OatDexFile(const char* dex_file_location, 2249 DexFileSource source, 2250 CreateTypeLookupTable create_type_lookup_table) 2251 : source_(source), 2252 create_type_lookup_table_(create_type_lookup_table), 2253 dex_file_size_(0), 2254 offset_(0), 2255 dex_file_location_size_(strlen(dex_file_location)), 2256 dex_file_location_data_(dex_file_location), 2257 dex_file_location_checksum_(0u), 2258 dex_file_offset_(0u), 2259 class_offsets_offset_(0u), 2260 lookup_table_offset_(0u), 2261 class_offsets_() { 2262 } 2263 2264 size_t OatWriter::OatDexFile::SizeOf() const { 2265 return sizeof(dex_file_location_size_) 2266 + dex_file_location_size_ 2267 + sizeof(dex_file_location_checksum_) 2268 + sizeof(dex_file_offset_) 2269 + sizeof(class_offsets_offset_) 2270 + sizeof(lookup_table_offset_); 2271 } 2272 2273 void OatWriter::OatDexFile::ReserveTypeLookupTable(OatWriter* oat_writer) { 2274 DCHECK_EQ(lookup_table_offset_, 0u); 2275 if (create_type_lookup_table_ == CreateTypeLookupTable::kCreate && !class_offsets_.empty()) { 2276 size_t table_size = TypeLookupTable::RawDataLength(class_offsets_.size()); 2277 if (table_size != 0u) { 2278 // Type tables are required to be 4 byte aligned. 2279 size_t original_offset = oat_writer->size_; 2280 size_t offset = RoundUp(original_offset, 4); 2281 oat_writer->size_oat_lookup_table_alignment_ += offset - original_offset; 2282 lookup_table_offset_ = offset; 2283 oat_writer->size_ = offset + table_size; 2284 oat_writer->size_oat_lookup_table_ += table_size; 2285 } 2286 } 2287 } 2288 2289 void OatWriter::OatDexFile::ReserveClassOffsets(OatWriter* oat_writer) { 2290 DCHECK_EQ(class_offsets_offset_, 0u); 2291 if (!class_offsets_.empty()) { 2292 // Class offsets are required to be 4 byte aligned. 2293 size_t original_offset = oat_writer->size_; 2294 size_t offset = RoundUp(original_offset, 4); 2295 oat_writer->size_oat_class_offsets_alignment_ += offset - original_offset; 2296 class_offsets_offset_ = offset; 2297 oat_writer->size_ = offset + GetClassOffsetsRawSize(); 2298 } 2299 } 2300 2301 bool OatWriter::OatDexFile::Write(OatWriter* oat_writer, OutputStream* out) const { 2302 const size_t file_offset = oat_writer->oat_data_offset_; 2303 DCHECK_OFFSET_(); 2304 2305 if (!out->WriteFully(&dex_file_location_size_, sizeof(dex_file_location_size_))) { 2306 PLOG(ERROR) << "Failed to write dex file location length to " << out->GetLocation(); 2307 return false; 2308 } 2309 oat_writer->size_oat_dex_file_location_size_ += sizeof(dex_file_location_size_); 2310 2311 if (!out->WriteFully(dex_file_location_data_, dex_file_location_size_)) { 2312 PLOG(ERROR) << "Failed to write dex file location data to " << out->GetLocation(); 2313 return false; 2314 } 2315 oat_writer->size_oat_dex_file_location_data_ += dex_file_location_size_; 2316 2317 if (!out->WriteFully(&dex_file_location_checksum_, sizeof(dex_file_location_checksum_))) { 2318 PLOG(ERROR) << "Failed to write dex file location checksum to " << out->GetLocation(); 2319 return false; 2320 } 2321 oat_writer->size_oat_dex_file_location_checksum_ += sizeof(dex_file_location_checksum_); 2322 2323 if (!out->WriteFully(&dex_file_offset_, sizeof(dex_file_offset_))) { 2324 PLOG(ERROR) << "Failed to write dex file offset to " << out->GetLocation(); 2325 return false; 2326 } 2327 oat_writer->size_oat_dex_file_offset_ += sizeof(dex_file_offset_); 2328 2329 if (!out->WriteFully(&class_offsets_offset_, sizeof(class_offsets_offset_))) { 2330 PLOG(ERROR) << "Failed to write class offsets offset to " << out->GetLocation(); 2331 return false; 2332 } 2333 oat_writer->size_oat_dex_file_class_offsets_offset_ += sizeof(class_offsets_offset_); 2334 2335 if (!out->WriteFully(&lookup_table_offset_, sizeof(lookup_table_offset_))) { 2336 PLOG(ERROR) << "Failed to write lookup table offset to " << out->GetLocation(); 2337 return false; 2338 } 2339 oat_writer->size_oat_dex_file_lookup_table_offset_ += sizeof(lookup_table_offset_); 2340 2341 return true; 2342 } 2343 2344 bool OatWriter::OatDexFile::WriteClassOffsets(OatWriter* oat_writer, OutputStream* out) { 2345 if (!out->WriteFully(class_offsets_.data(), GetClassOffsetsRawSize())) { 2346 PLOG(ERROR) << "Failed to write oat class offsets for " << GetLocation() 2347 << " to " << out->GetLocation(); 2348 return false; 2349 } 2350 oat_writer->size_oat_class_offsets_ += GetClassOffsetsRawSize(); 2351 return true; 2352 } 2353 2354 OatWriter::OatClass::OatClass(size_t offset, 2355 const dchecked_vector<CompiledMethod*>& compiled_methods, 2356 uint32_t num_non_null_compiled_methods, 2357 mirror::Class::Status status) 2358 : compiled_methods_(compiled_methods) { 2359 uint32_t num_methods = compiled_methods.size(); 2360 CHECK_LE(num_non_null_compiled_methods, num_methods); 2361 2362 offset_ = offset; 2363 oat_method_offsets_offsets_from_oat_class_.resize(num_methods); 2364 2365 // Since both kOatClassNoneCompiled and kOatClassAllCompiled could 2366 // apply when there are 0 methods, we just arbitrarily say that 0 2367 // methods means kOatClassNoneCompiled and that we won't use 2368 // kOatClassAllCompiled unless there is at least one compiled 2369 // method. This means in an interpretter only system, we can assert 2370 // that all classes are kOatClassNoneCompiled. 2371 if (num_non_null_compiled_methods == 0) { 2372 type_ = kOatClassNoneCompiled; 2373 } else if (num_non_null_compiled_methods == num_methods) { 2374 type_ = kOatClassAllCompiled; 2375 } else { 2376 type_ = kOatClassSomeCompiled; 2377 } 2378 2379 status_ = status; 2380 method_offsets_.resize(num_non_null_compiled_methods); 2381 method_headers_.resize(num_non_null_compiled_methods); 2382 2383 uint32_t oat_method_offsets_offset_from_oat_class = sizeof(type_) + sizeof(status_); 2384 if (type_ == kOatClassSomeCompiled) { 2385 method_bitmap_.reset(new BitVector(num_methods, false, Allocator::GetMallocAllocator())); 2386 method_bitmap_size_ = method_bitmap_->GetSizeOf(); 2387 oat_method_offsets_offset_from_oat_class += sizeof(method_bitmap_size_); 2388 oat_method_offsets_offset_from_oat_class += method_bitmap_size_; 2389 } else { 2390 method_bitmap_ = nullptr; 2391 method_bitmap_size_ = 0; 2392 } 2393 2394 for (size_t i = 0; i < num_methods; i++) { 2395 CompiledMethod* compiled_method = compiled_methods_[i]; 2396 if (compiled_method == nullptr) { 2397 oat_method_offsets_offsets_from_oat_class_[i] = 0; 2398 } else { 2399 oat_method_offsets_offsets_from_oat_class_[i] = oat_method_offsets_offset_from_oat_class; 2400 oat_method_offsets_offset_from_oat_class += sizeof(OatMethodOffsets); 2401 if (type_ == kOatClassSomeCompiled) { 2402 method_bitmap_->SetBit(i); 2403 } 2404 } 2405 } 2406 } 2407 2408 size_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatHeader( 2409 size_t class_def_method_index_) const { 2410 uint32_t method_offset = GetOatMethodOffsetsOffsetFromOatClass(class_def_method_index_); 2411 if (method_offset == 0) { 2412 return 0; 2413 } 2414 return offset_ + method_offset; 2415 } 2416 2417 size_t OatWriter::OatClass::GetOatMethodOffsetsOffsetFromOatClass( 2418 size_t class_def_method_index_) const { 2419 return oat_method_offsets_offsets_from_oat_class_[class_def_method_index_]; 2420 } 2421 2422 size_t OatWriter::OatClass::SizeOf() const { 2423 return sizeof(status_) 2424 + sizeof(type_) 2425 + ((method_bitmap_size_ == 0) ? 0 : sizeof(method_bitmap_size_)) 2426 + method_bitmap_size_ 2427 + (sizeof(method_offsets_[0]) * method_offsets_.size()); 2428 } 2429 2430 bool OatWriter::OatClass::Write(OatWriter* oat_writer, 2431 OutputStream* out, 2432 const size_t file_offset) const { 2433 DCHECK_OFFSET_(); 2434 if (!out->WriteFully(&status_, sizeof(status_))) { 2435 PLOG(ERROR) << "Failed to write class status to " << out->GetLocation(); 2436 return false; 2437 } 2438 oat_writer->size_oat_class_status_ += sizeof(status_); 2439 2440 if (!out->WriteFully(&type_, sizeof(type_))) { 2441 PLOG(ERROR) << "Failed to write oat class type to " << out->GetLocation(); 2442 return false; 2443 } 2444 oat_writer->size_oat_class_type_ += sizeof(type_); 2445 2446 if (method_bitmap_size_ != 0) { 2447 CHECK_EQ(kOatClassSomeCompiled, type_); 2448 if (!out->WriteFully(&method_bitmap_size_, sizeof(method_bitmap_size_))) { 2449 PLOG(ERROR) << "Failed to write method bitmap size to " << out->GetLocation(); 2450 return false; 2451 } 2452 oat_writer->size_oat_class_method_bitmaps_ += sizeof(method_bitmap_size_); 2453 2454 if (!out->WriteFully(method_bitmap_->GetRawStorage(), method_bitmap_size_)) { 2455 PLOG(ERROR) << "Failed to write method bitmap to " << out->GetLocation(); 2456 return false; 2457 } 2458 oat_writer->size_oat_class_method_bitmaps_ += method_bitmap_size_; 2459 } 2460 2461 if (!out->WriteFully(method_offsets_.data(), GetMethodOffsetsRawSize())) { 2462 PLOG(ERROR) << "Failed to write method offsets to " << out->GetLocation(); 2463 return false; 2464 } 2465 oat_writer->size_oat_class_method_offsets_ += GetMethodOffsetsRawSize(); 2466 return true; 2467 } 2468 2469 } // namespace art 2470