diff options
27 files changed, 418 insertions, 143 deletions
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc index b3a92e59ac..c7e9cdaae0 100644 --- a/dex2oat/linker/oat_writer.cc +++ b/dex2oat/linker/oat_writer.cc @@ -372,6 +372,7 @@ OatWriter::OatWriter(bool compiling_boot_image, dex_files_(nullptr), vdex_size_(0u), vdex_dex_files_offset_(0u), + vdex_dex_shared_data_offset_(0u), vdex_verifier_deps_offset_(0u), vdex_quickening_info_offset_(0u), oat_size_(0u), @@ -3363,6 +3364,54 @@ bool OatWriter::WriteDexFiles(OutputStream* out, File* file, bool update_input_v return false; } } + + // Write shared dex file data section and fix up the dex file headers. + vdex_dex_shared_data_offset_ = vdex_size_; + if (dex_container_ != nullptr) { + DexContainer::Section* const section = dex_container_->GetDataSection(); + if (section->Size() > 0) { + const uint32_t shared_data_offset = vdex_size_; + const off_t existing_offset = out->Seek(0, kSeekCurrent); + if (static_cast<uint32_t>(existing_offset) != shared_data_offset) { + LOG(ERROR) << "Expected offset " << shared_data_offset << " but got " << existing_offset; + return false; + } + const uint32_t shared_data_size = section->Size(); + if (!out->WriteFully(section->Begin(), shared_data_size)) { + LOG(ERROR) << "Failed to write shared data!"; + return false; + } + // Fix up the dex headers to have correct offsets to the data section. + for (OatDexFile& oat_dex_file : oat_dex_files_) { + // Overwrite the header by reading it, updating the offset, and writing it back out. + DexFile::Header header; + if (!file->PreadFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) { + LOG(ERROR) << "Failed to read dex header for updating"; + return false; + } + CHECK(CompactDexFile::IsMagicValid(header.magic_)) << "Must be compact dex"; + CHECK_GT(shared_data_offset, oat_dex_file.dex_file_offset_); + // Offset is from the dex file base. + header.data_off_ = shared_data_offset - oat_dex_file.dex_file_offset_; + // The size should already be what part of the data buffer may be used by the dex. + CHECK_LE(header.data_size_, shared_data_size); + if (!file->PwriteFully(&header, sizeof(header), oat_dex_file.dex_file_offset_)) { + LOG(ERROR) << "Failed to write dex header for updating"; + return false; + } + } + vdex_size_ += shared_data_size; + size_dex_file_ += shared_data_size; + section->Clear(); + if (!out->Flush()) { + PLOG(ERROR) << "Failed to flush after writing shared dex section."; + return false; + } + } + dex_container_.reset(); + } + } else { + vdex_dex_shared_data_offset_ = vdex_size_; } return true; @@ -3521,20 +3570,23 @@ bool OatWriter::LayoutAndWriteDexFile(OutputStream* out, OatDexFile* oat_dex_fil options.compact_dex_level_ = compact_dex_level_; options.update_checksum_ = true; DexLayout dex_layout(options, profile_compilation_info_, /*file*/ nullptr, /*header*/ nullptr); - std::unique_ptr<DexContainer> out_data; - dex_layout.ProcessDexFile(location.c_str(), dex_file.get(), 0, &out_data); + dex_layout.ProcessDexFile(location.c_str(), dex_file.get(), 0, &dex_container_); oat_dex_file->dex_sections_layout_ = dex_layout.GetSections(); // Dex layout can affect the size of the dex file, so we update here what we have set // when adding the dex file as a source. const UnalignedDexFileHeader* header = - AsUnalignedDexFileHeader(out_data->GetMainSection()->Begin()); + AsUnalignedDexFileHeader(dex_container_->GetMainSection()->Begin()); oat_dex_file->dex_file_size_ = header->file_size_; if (!WriteDexFile(out, oat_dex_file, - out_data->GetMainSection()->Begin(), + dex_container_->GetMainSection()->Begin(), /* update_input_vdex */ false)) { return false; } + if (dex_container_ != nullptr) { + // Clear the main section in case we write more data into the container. + dex_container_->GetMainSection()->Clear(); + } CHECK_EQ(oat_dex_file->dex_file_location_checksum_, dex_file->GetLocationChecksum()); return true; } @@ -3996,12 +4048,14 @@ bool OatWriter::WriteChecksumsAndVdexHeader(OutputStream* vdex_out) { DCHECK_NE(vdex_verifier_deps_offset_, 0u); DCHECK_NE(vdex_quickening_info_offset_, 0u); - size_t dex_section_size = vdex_verifier_deps_offset_ - vdex_dex_files_offset_; + size_t dex_section_size = vdex_dex_shared_data_offset_ - vdex_dex_files_offset_; + size_t dex_shared_data_size = vdex_verifier_deps_offset_ - vdex_dex_shared_data_offset_; size_t verifier_deps_section_size = vdex_quickening_info_offset_ - vdex_verifier_deps_offset_; size_t quickening_info_section_size = vdex_size_ - vdex_quickening_info_offset_; VdexFile::Header vdex_header(oat_dex_files_.size(), dex_section_size, + dex_shared_data_size, verifier_deps_section_size, quickening_info_section_size); if (!vdex_out->WriteFully(&vdex_header, sizeof(VdexFile::Header))) { diff --git a/dex2oat/linker/oat_writer.h b/dex2oat/linker/oat_writer.h index c08c05a93b..dfcaafc336 100644 --- a/dex2oat/linker/oat_writer.h +++ b/dex2oat/linker/oat_writer.h @@ -41,6 +41,7 @@ namespace art { class BitVector; class CompiledMethod; class CompilerDriver; +class DexContainer; class ProfileCompilationInfo; class TimingLogger; class TypeLookupTable; @@ -382,6 +383,9 @@ class OatWriter { // Offset of section holding Dex files inside Vdex. size_t vdex_dex_files_offset_; + // Offset of section holding shared dex data section in the Vdex. + size_t vdex_dex_shared_data_offset_; + // Offset of section holding VerifierDeps inside Vdex. size_t vdex_verifier_deps_offset_; @@ -518,6 +522,9 @@ class OatWriter { // This pointer is only non-null after InitOatCodeDexFiles succeeds. std::unique_ptr<OrderedMethodList> ordered_methods_; + // Container of shared dex data. + std::unique_ptr<DexContainer> dex_container_; + DISALLOW_COPY_AND_ASSIGN(OatWriter); }; diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc index 2f601b6b1a..ef31c3f212 100644 --- a/dexlayout/compact_dex_writer.cc +++ b/dexlayout/compact_dex_writer.cc @@ -167,6 +167,7 @@ uint32_t CompactDexWriter::WriteCodeItem(Stream* stream, code_item->GetOffset()); if (deduped_offset != Deduper::kDidNotDedupe) { code_item->SetOffset(deduped_offset); + stream->Clear(start_offset, stream->Tell() - start_offset); // Undo the offset for all that we wrote since we deduped. stream->Seek(start_offset); } @@ -287,9 +288,16 @@ void CompactDexWriter::Write(DexContainer* output) { CHECK(output->IsCompactDexContainer()); Container* const container = down_cast<Container*>(output); // For now, use the same stream for both data and metadata. - Stream stream(output->GetMainSection()); - Stream* main_stream = &stream; - Stream* data_stream = &stream; + Stream temp_main_stream(output->GetMainSection()); + Stream temp_data_stream(output->GetDataSection()); + Stream* main_stream = &temp_main_stream; + Stream* data_stream = &temp_data_stream; + + // We want offset 0 to be reserved for null, seek to the data section alignment or the end of the + // section. + data_stream->Seek(std::max( + static_cast<uint32_t>(output->GetDataSection()->Size()), + kDataSectionAlignment)); code_item_dedupe_ = &container->code_item_dedupe_; // Starting offset is right after the header. @@ -312,11 +320,9 @@ void CompactDexWriter::Write(DexContainer* output) { WriteCallSiteIds(main_stream, /*reserve_only*/ true); WriteMethodHandles(main_stream); - uint32_t data_offset_ = 0u; if (compute_offsets_) { // Data section. data_stream->AlignTo(kDataSectionAlignment); - data_offset_ = data_stream->Tell(); } // Write code item first to minimize the space required for encoded methods. @@ -362,19 +368,9 @@ void CompactDexWriter::Write(DexContainer* output) { } else { data_stream->Seek(collection.MapListOffset()); } - GenerateAndWriteMapItems(data_stream); - data_stream->AlignTo(kDataSectionAlignment); // Map items are included in the data section. - if (compute_offsets_) { - header_->SetDataSize(data_stream->Tell() - data_offset_); - if (header_->DataSize() != 0) { - // Offset must be zero when the size is zero. - header_->SetDataOffset(data_offset_); - } else { - header_->SetDataOffset(0u); - } - } + GenerateAndWriteMapItems(data_stream); // Write link data if it exists. const std::vector<uint8_t>& link_data = collection.LinkData(); @@ -391,19 +387,39 @@ void CompactDexWriter::Write(DexContainer* output) { // Write debug info offset table last to make dex file verifier happy. WriteDebugInfoOffsetTable(data_stream); + data_stream->AlignTo(kDataSectionAlignment); + if (compute_offsets_) { + header_->SetDataSize(data_stream->Tell()); + if (header_->DataSize() != 0) { + // Offset must be zero when the size is zero. + main_stream->AlignTo(kDataSectionAlignment); + // For now, default to saying the data is right after the main stream. + header_->SetDataOffset(main_stream->Tell()); + header_->SetDataOffset(0u); + } else { + header_->SetDataOffset(0u); + } + } + // Write header last. if (compute_offsets_) { header_->SetFileSize(main_stream->Tell()); } WriteHeader(main_stream); + // Trim sections to make sure they are sized properly. + output->GetMainSection()->Resize(header_->FileSize()); + output->GetDataSection()->Resize(data_stream->Tell()); + if (dex_layout_->GetOptions().update_checksum_) { - header_->SetChecksum(DexFile::CalculateChecksum(main_stream->Begin(), header_->FileSize())); + // Compute the cdex section (also covers the used part of the data section). + header_->SetChecksum(CompactDexFile::CalculateChecksum(output->GetMainSection()->Begin(), + output->GetMainSection()->Size(), + output->GetDataSection()->Begin(), + output->GetDataSection()->Size())); // Rewrite the header with the calculated checksum. WriteHeader(main_stream); } - // Trim the map to make it sized as large as the dex file. - output->GetMainSection()->Resize(header_->FileSize()); } std::unique_ptr<DexContainer> CompactDexWriter::CreateDexContainer() const { diff --git a/dexlayout/dex_container.h b/dexlayout/dex_container.h index 7c426cbc53..2b9a5f9959 100644 --- a/dexlayout/dex_container.h +++ b/dexlayout/dex_container.h @@ -43,6 +43,9 @@ class DexContainer { // Resize the backing storage. virtual void Resize(size_t size) = 0; + // Clear the container. + virtual void Clear() = 0; + // Returns the end of the memory region. uint8_t* End() { return Begin() + Size(); @@ -66,6 +69,10 @@ class DexContainer { data_.resize(size, 0u); } + void Clear() OVERRIDE { + data_.clear(); + } + private: std::vector<uint8_t> data_; }; diff --git a/dexlayout/dex_ir.cc b/dexlayout/dex_ir.cc index fb7dff63b7..1525d537b7 100644 --- a/dexlayout/dex_ir.cc +++ b/dexlayout/dex_ir.cc @@ -280,7 +280,7 @@ void Collections::ReadEncodedValue(const DexFile& dex_file, } case DexFile::kDexAnnotationArray: { EncodedValueVector* values = new EncodedValueVector(); - const uint32_t offset = *data - dex_file.Begin(); + const uint32_t offset = *data - dex_file.DataBegin(); const uint32_t size = DecodeUnsignedLeb128(data); // Decode all elements. for (uint32_t i = 0; i < size; i++) { @@ -440,7 +440,7 @@ void Collections::AddAnnotationsFromMapListSection(const DexFile& dex_file, AnnotationItem* Collections::CreateAnnotationItem(const DexFile& dex_file, const DexFile::AnnotationItem* annotation) { const uint8_t* const start_data = reinterpret_cast<const uint8_t*>(annotation); - const uint32_t offset = start_data - dex_file.Begin(); + const uint32_t offset = start_data - dex_file.DataBegin(); AnnotationItem* annotation_item = annotation_items_map_.GetExistingObject(offset); if (annotation_item == nullptr) { uint8_t visibility = annotation->visibility_; @@ -772,8 +772,7 @@ ClassData* Collections::CreateClassData( void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) { // Iterate through the map list and set the offset of the CallSiteIds and MethodHandleItems. - const DexFile::MapList* map = - reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + MapListOffset()); + const DexFile::MapList* map = dex_file.GetMapList(); for (uint32_t i = 0; i < map->size_; ++i) { const DexFile::MapItem* item = map->list_ + i; switch (item->type_) { @@ -799,7 +798,7 @@ void Collections::CreateCallSitesAndMethodHandles(const DexFile& dex_file) { void Collections::CreateCallSiteId(const DexFile& dex_file, uint32_t i) { const DexFile::CallSiteIdItem& disk_call_site_id = dex_file.GetCallSiteId(i); - const uint8_t* disk_call_item_ptr = dex_file.Begin() + disk_call_site_id.data_off_; + const uint8_t* disk_call_item_ptr = dex_file.DataBegin() + disk_call_site_id.data_off_; EncodedArrayItem* call_site_item = CreateEncodedArrayItem(dex_file, disk_call_item_ptr, disk_call_site_id.data_off_); diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc index 231826b7a8..3ec163cea1 100644 --- a/dexlayout/dex_ir_builder.cc +++ b/dexlayout/dex_ir_builder.cc @@ -83,8 +83,8 @@ Header* DexIrBuilder(const DexFile& dex_file, bool eagerly_assign_offsets) { // Load the link data if it exists. collections.SetLinkData(std::vector<uint8_t>( - dex_file.Begin() + dex_file.GetHeader().link_off_, - dex_file.Begin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_)); + dex_file.DataBegin() + dex_file.GetHeader().link_off_, + dex_file.DataBegin() + dex_file.GetHeader().link_off_ + dex_file.GetHeader().link_size_)); return header; } @@ -92,8 +92,7 @@ Header* DexIrBuilder(const DexFile& dex_file, bool eagerly_assign_offsets) { static void CheckAndSetRemainingOffsets(const DexFile& dex_file, Collections* collections) { const DexFile::Header& disk_header = dex_file.GetHeader(); // Read MapItems and validate/set remaining offsets. - const DexFile::MapList* map = - reinterpret_cast<const DexFile::MapList*>(dex_file.Begin() + disk_header.map_off_); + const DexFile::MapList* map = dex_file.GetMapList(); const uint32_t count = map->size_; for (uint32_t i = 0; i < count; ++i) { const DexFile::MapItem* item = map->list_ + i; diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc index eb038a008b..67d0f9ac68 100644 --- a/dexlayout/dex_writer.cc +++ b/dexlayout/dex_writer.cc @@ -30,6 +30,8 @@ namespace art { +constexpr uint32_t DexWriter::kDataSectionAlignment; + static size_t EncodeIntValue(int32_t value, uint8_t* buffer) { size_t length = 0; if (value >= 0) { diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc index d33a0bde03..1b32f7b0d9 100644 --- a/dexlayout/dexlayout.cc +++ b/dexlayout/dexlayout.cc @@ -1838,13 +1838,17 @@ void DexLayout::OutputDexFile(const DexFile* input_dex_file, } } DexWriter::Output(this, dex_container, compute_offsets); - DexContainer* const container = dex_container->get(); - DexContainer::Section* const main_section = container->GetMainSection(); - DexContainer::Section* const data_section = container->GetDataSection(); - CHECK_EQ(data_section->Size(), 0u) << "Unsupported"; if (new_file != nullptr) { + DexContainer* const container = dex_container->get(); + DexContainer::Section* const main_section = container->GetMainSection(); if (!new_file->WriteFully(main_section->Begin(), main_section->Size())) { - LOG(ERROR) << "Failed tow write dex file to " << dex_file_location; + LOG(ERROR) << "Failed to write main section for dex file " << dex_file_location; + new_file->Erase(); + return; + } + DexContainer::Section* const data_section = container->GetDataSection(); + if (!new_file->WriteFully(data_section->Begin(), data_section->Size())) { + LOG(ERROR) << "Failed to write data section for dex file " << dex_file_location; new_file->Erase(); return; } @@ -1919,17 +1923,22 @@ void DexLayout::ProcessDexFile(const char* file_name, // Dex file verifier cannot handle compact dex. bool verify = options_.compact_dex_level_ == CompactDexLevel::kCompactDexLevelNone; const ArtDexFileLoader dex_file_loader; - DexContainer::Section* section = (*dex_container)->GetMainSection(); - DCHECK_EQ(file_size, section->Size()); + DexContainer::Section* const main_section = (*dex_container)->GetMainSection(); + DexContainer::Section* const data_section = (*dex_container)->GetDataSection(); + DCHECK_EQ(file_size, main_section->Size()) + << main_section->Size() << " " << data_section->Size(); std::unique_ptr<const DexFile> output_dex_file( - dex_file_loader.Open(section->Begin(), - file_size, - location, - /* checksum */ 0, - /*oat_dex_file*/ nullptr, - verify, - /*verify_checksum*/ false, - &error_msg)); + dex_file_loader.OpenWithDataSection( + main_section->Begin(), + main_section->Size(), + data_section->Begin(), + data_section->Size(), + location, + /* checksum */ 0, + /*oat_dex_file*/ nullptr, + verify, + /*verify_checksum*/ false, + &error_msg)); CHECK(output_dex_file != nullptr) << "Failed to re-open output file:" << error_msg; // Do IR-level comparison between input and output. This check ignores potential differences diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index f2a69f3bb3..f7151b350d 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -1156,6 +1156,7 @@ class OatDumper { // Vdex unquicken output should match original input bytecode uint32_t orig_checksum = reinterpret_cast<DexFile::Header*>(const_cast<uint8_t*>(dex_file->Begin()))->checksum_; + CHECK_EQ(orig_checksum, dex_file->CalculateChecksum()); if (orig_checksum != dex_file->CalculateChecksum()) { os << "Unexpected checksum from unquicken dex file '" << dex_file_location << "'\n"; return false; @@ -1208,7 +1209,11 @@ class OatDumper { return false; } - if (!file->WriteFully(dex_file->Begin(), fsize)) { + bool success = false; + success = file->WriteFully(dex_file->Begin(), fsize); + // } + + if (!success) { os << "Failed to write dex file"; file->Erase(); return false; diff --git a/openjdkjvmti/fixed_up_dex_file.cc b/openjdkjvmti/fixed_up_dex_file.cc index 323137aa5b..cc56a7b714 100644 --- a/openjdkjvmti/fixed_up_dex_file.cc +++ b/openjdkjvmti/fixed_up_dex_file.cc @@ -70,8 +70,21 @@ static void DoDexUnquicken(const art::DexFile& new_dex_file, const art::DexFile& std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(const art::DexFile& original) { // Copy the data into mutable memory. std::vector<unsigned char> data; - data.resize(original.Size()); - memcpy(data.data(), original.Begin(), original.Size()); + if (original.IsCompactDexFile()) { + // Compact dex has a separate data section that is relative from the original dex. + // We need to copy the shared data section so that dequickening doesn't change anything. + data.resize(original.Size() + original.DataSize()); + memcpy(data.data(), original.Begin(), original.Size()); + memcpy(data.data() + original.Size(), original.DataBegin(), original.DataSize()); + // Go patch up the header to point to the copied data section. + art::CompactDexFile::Header* const header = + const_cast<art::CompactDexFile::Header*>(art::CompactDexFile::Header::At(data.data())); + header->data_off_ = original.Size(); + header->data_size_ = original.DataSize(); + } else { + data.resize(original.Size()); + memcpy(data.data(), original.Begin(), original.Size()); + } std::string error; const art::ArtDexFileLoader dex_file_loader; std::unique_ptr<const art::DexFile> new_dex_file(dex_file_loader.Open( @@ -105,6 +118,7 @@ std::unique_ptr<FixedUpDexFile> FixedUpDexFile::Create(const art::DexFile& origi 0, &dex_container); art::DexContainer::Section* main_section = dex_container->GetMainSection(); + CHECK_EQ(dex_container->GetDataSection()->Size(), 0u); // Overwrite the dex file stored in data with the new result. data.clear(); data.insert(data.end(), main_section->Begin(), main_section->End()); diff --git a/runtime/dex/art_dex_file_loader.cc b/runtime/dex/art_dex_file_loader.cc index dee736ecff..08cf30d5bf 100644 --- a/runtime/dex/art_dex_file_loader.cc +++ b/runtime/dex/art_dex_file_loader.cc @@ -154,6 +154,8 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const uint8_t* base, ScopedTrace trace(std::string("Open dex file from RAM ") + location); return OpenCommon(base, size, + /*data_base*/ nullptr, + /*data_size*/ 0u, location, location_checksum, oat_dex_file, @@ -182,6 +184,8 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::Open(const std::string& locatio std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(), map->Size(), + /*data_base*/ nullptr, + /*data_size*/ 0u, location, location_checksum, kNoOatDexFile, @@ -303,6 +307,8 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::OpenFile(int fd, std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(), map->Size(), + /*data_base*/ nullptr, + /*data_size*/ 0u, location, dex_header->checksum_, kNoOatDexFile, @@ -370,6 +376,8 @@ std::unique_ptr<const DexFile> ArtDexFileLoader::OpenOneDexFileFromZip( VerifyResult verify_result; std::unique_ptr<DexFile> dex_file = OpenCommon(map->Begin(), map->Size(), + /*data_base*/ nullptr, + /*data_size*/ 0u, location, zip_entry->GetCrc32(), kNoOatDexFile, diff --git a/runtime/dex/code_item_accessors-no_art-inl.h b/runtime/dex/code_item_accessors-no_art-inl.h index 6a99009b00..a243a4a6f4 100644 --- a/runtime/dex/code_item_accessors-no_art-inl.h +++ b/runtime/dex/code_item_accessors-no_art-inl.h @@ -50,7 +50,7 @@ inline void CodeItemInstructionAccessor::Init(const StandardDexFile::CodeItem& c inline void CodeItemInstructionAccessor::Init(const DexFile& dex_file, const DexFile::CodeItem* code_item) { if (code_item != nullptr) { - DCHECK(dex_file.HasAddress(code_item)); + DCHECK(dex_file.IsInDataSection(code_item)); if (dex_file.IsCompactDexFile()) { Init(down_cast<const CompactDexFile::CodeItem&>(*code_item)); } else { diff --git a/runtime/dex/code_item_accessors_test.cc b/runtime/dex/code_item_accessors_test.cc index 3380be8acf..8e2548bf3d 100644 --- a/runtime/dex/code_item_accessors_test.cc +++ b/runtime/dex/code_item_accessors_test.cc @@ -39,8 +39,12 @@ std::unique_ptr<const DexFile> CreateFakeDex(bool compact_dex) { &error_msg)); CHECK(map != nullptr) << error_msg; if (compact_dex) { - CompactDexFile::WriteMagic(map->Begin()); - CompactDexFile::WriteCurrentVersion(map->Begin()); + CompactDexFile::Header* header = + const_cast<CompactDexFile::Header*>(CompactDexFile::Header::At(map->Begin())); + CompactDexFile::WriteMagic(header->magic_); + CompactDexFile::WriteCurrentVersion(header->magic_); + header->data_off_ = 0; + header->data_size_ = map->Size(); } else { StandardDexFile::WriteMagic(map->Begin()); StandardDexFile::WriteCurrentVersion(map->Begin()); diff --git a/runtime/dex/compact_dex_file.cc b/runtime/dex/compact_dex_file.cc index ff193ffb07..37f5d0074c 100644 --- a/runtime/dex/compact_dex_file.cc +++ b/runtime/dex/compact_dex_file.cc @@ -56,27 +56,52 @@ bool CompactDexFile::SupportsDefaultMethods() const { } uint32_t CompactDexFile::GetCodeItemSize(const DexFile::CodeItem& item) const { - // TODO: Clean up this temporary code duplication with StandardDexFile. Eventually the - // implementations will differ. - DCHECK(HasAddress(&item)); + DCHECK(IsInDataSection(&item)); return reinterpret_cast<uintptr_t>(CodeItemDataAccessor(*this, &item).CodeItemDataEnd()) - reinterpret_cast<uintptr_t>(&item); } + +uint32_t CompactDexFile::CalculateChecksum(const uint8_t* base_begin, + size_t base_size, + const uint8_t* data_begin, + size_t data_size) { + Header temp_header(*Header::At(base_begin)); + // Zero out fields that are not included in the sum. + temp_header.checksum_ = 0u; + temp_header.data_off_ = 0u; + temp_header.data_size_ = 0u; + uint32_t checksum = ChecksumMemoryRange(reinterpret_cast<const uint8_t*>(&temp_header), + sizeof(temp_header)); + // Exclude the header since we already computed it's checksum. + checksum = (checksum * 31) ^ ChecksumMemoryRange(base_begin + sizeof(temp_header), + base_size - sizeof(temp_header)); + checksum = (checksum * 31) ^ ChecksumMemoryRange(data_begin, data_size); + return checksum; +} + +uint32_t CompactDexFile::CalculateChecksum() const { + return CalculateChecksum(Begin(), Size(), DataBegin(), DataSize()); +} + CompactDexFile::CompactDexFile(const uint8_t* base, size_t size, + const uint8_t* data_begin, + size_t data_size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, DexFileContainer* container) : DexFile(base, size, + data_begin, + data_size, location, location_checksum, oat_dex_file, container, /*is_compact_dex*/ true), - debug_info_offsets_(Begin() + GetHeader().debug_info_offsets_pos_, + debug_info_offsets_(DataBegin() + GetHeader().debug_info_offsets_pos_, GetHeader().debug_info_base_, GetHeader().debug_info_offsets_table_offset_) {} diff --git a/runtime/dex/compact_dex_file.h b/runtime/dex/compact_dex_file.h index 8dad84d5cd..1ecff04cba 100644 --- a/runtime/dex/compact_dex_file.h +++ b/runtime/dex/compact_dex_file.h @@ -35,10 +35,22 @@ class CompactDexFile : public DexFile { class Header : public DexFile::Header { public: + static const Header* At(const void* at) { + return reinterpret_cast<const Header*>(at); + } + uint32_t GetFeatureFlags() const { return feature_flags_; } + uint32_t GetDataOffset() const { + return data_off_; + } + + uint32_t GetDataSize() const { + return data_size_; + } + private: uint32_t feature_flags_ = 0u; @@ -245,9 +257,17 @@ class CompactDexFile : public DexFile { return debug_info_offsets_.GetDebugInfoOffset(dex_method_index); } + static uint32_t CalculateChecksum(const uint8_t* base_begin, + size_t base_size, + const uint8_t* data_begin, + size_t data_size); + virtual uint32_t CalculateChecksum() const OVERRIDE; + private: CompactDexFile(const uint8_t* base, size_t size, + const uint8_t* data_begin, + size_t data_size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, diff --git a/runtime/dex/dex_file-inl.h b/runtime/dex/dex_file-inl.h index 9b14514cf4..aa53daac35 100644 --- a/runtime/dex/dex_file-inl.h +++ b/runtime/dex/dex_file-inl.h @@ -29,14 +29,14 @@ namespace art { inline int32_t DexFile::GetStringLength(const StringId& string_id) const { - const uint8_t* ptr = begin_ + string_id.string_data_off_; + const uint8_t* ptr = DataBegin() + string_id.string_data_off_; return DecodeUnsignedLeb128(&ptr); } inline const char* DexFile::GetStringDataAndUtf16Length(const StringId& string_id, uint32_t* utf16_length) const { DCHECK(utf16_length != nullptr) << GetLocation(); - const uint8_t* ptr = begin_ + string_id.string_data_off_; + const uint8_t* ptr = DataBegin() + string_id.string_data_off_; *utf16_length = DecodeUnsignedLeb128(&ptr); return reinterpret_cast<const char*>(ptr); } diff --git a/runtime/dex/dex_file.cc b/runtime/dex/dex_file.cc index 16325b83f6..6ec997c93f 100644 --- a/runtime/dex/dex_file.cc +++ b/runtime/dex/dex_file.cc @@ -50,9 +50,12 @@ uint32_t DexFile::CalculateChecksum() const { } uint32_t DexFile::CalculateChecksum(const uint8_t* begin, size_t size) { - const uint32_t non_sum = OFFSETOF_MEMBER(DexFile::Header, signature_); - const uint8_t* non_sum_ptr = begin + non_sum; - return adler32(adler32(0L, Z_NULL, 0), non_sum_ptr, size - non_sum); + const uint32_t non_sum_bytes = OFFSETOF_MEMBER(DexFile::Header, signature_); + return ChecksumMemoryRange(begin + non_sum_bytes, size - non_sum_bytes); +} + +uint32_t DexFile::ChecksumMemoryRange(const uint8_t* begin, size_t size) { + return adler32(adler32(0L, Z_NULL, 0), begin, size); } int DexFile::GetPermissions() const { @@ -77,6 +80,8 @@ bool DexFile::DisableWrite() const { DexFile::DexFile(const uint8_t* base, size_t size, + const uint8_t* data_begin, + size_t data_size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, @@ -84,6 +89,8 @@ DexFile::DexFile(const uint8_t* base, bool is_compact_dex) : begin_(base), size_(size), + data_begin_(data_begin), + data_size_(data_size), location_(location), location_checksum_(location_checksum), header_(reinterpret_cast<const Header*>(base)), @@ -149,7 +156,7 @@ bool DexFile::CheckMagicAndVersion(std::string* error_msg) const { } void DexFile::InitializeSectionsFromMapList() { - const MapList* map_list = reinterpret_cast<const MapList*>(begin_ + header_->map_off_); + const MapList* map_list = reinterpret_cast<const MapList*>(DataBegin() + header_->map_off_); if (header_->map_off_ == 0 || header_->map_off_ > size_) { // Bad offset. The dex file verifier runs after this method and will reject the file. return; @@ -166,10 +173,10 @@ void DexFile::InitializeSectionsFromMapList() { for (size_t i = 0; i < count; ++i) { const MapItem& map_item = map_list->list_[i]; if (map_item.type_ == kDexTypeMethodHandleItem) { - method_handles_ = reinterpret_cast<const MethodHandleItem*>(begin_ + map_item.offset_); + method_handles_ = reinterpret_cast<const MethodHandleItem*>(DataBegin() + map_item.offset_); num_method_handles_ = map_item.size_; } else if (map_item.type_ == kDexTypeCallSiteIdItem) { - call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(begin_ + map_item.offset_); + call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(DataBegin() + map_item.offset_); num_call_site_ids_ = map_item.size_; } } diff --git a/runtime/dex/dex_file.h b/runtime/dex/dex_file.h index 511ce312cd..ef25797274 100644 --- a/runtime/dex/dex_file.h +++ b/runtime/dex/dex_file.h @@ -646,11 +646,7 @@ class DexFile { const ClassDef* FindClassDef(dex::TypeIndex type_idx) const; const TypeList* GetInterfacesList(const ClassDef& class_def) const { - if (class_def.interfaces_off_ == 0) { - return nullptr; - } - const uint8_t* addr = begin_ + class_def.interfaces_off_; - return reinterpret_cast<const TypeList*>(addr); + return DataPointer<TypeList>(class_def.interfaces_off_); } uint32_t NumMethodHandles() const { @@ -673,17 +669,13 @@ class DexFile { // Returns a pointer to the raw memory mapped class_data_item const uint8_t* GetClassData(const ClassDef& class_def) const { - return (class_def.class_data_off_ == 0) ? nullptr : begin_ + class_def.class_data_off_; + return DataPointer<uint8_t>(class_def.class_data_off_); } - // + // Return the code item for a provided offset. const CodeItem* GetCodeItem(const uint32_t code_off) const { - DCHECK_LT(code_off, size_) << "Code item offset larger then maximum allowed offset"; - if (code_off == 0) { - return nullptr; // native or abstract method - } - const uint8_t* addr = begin_ + code_off; - return reinterpret_cast<const CodeItem*>(addr); + // May be null for native or abstract methods. + return DataPointer<CodeItem>(code_off); } const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const; @@ -728,17 +720,15 @@ class DexFile { const char* GetShorty(uint32_t proto_idx) const; const TypeList* GetProtoParameters(const ProtoId& proto_id) const { - return (proto_id.parameters_off_ == 0) - ? nullptr - : reinterpret_cast<const TypeList*>(begin_ + proto_id.parameters_off_); + return DataPointer<TypeList>(proto_id.parameters_off_); } const uint8_t* GetEncodedStaticFieldValuesArray(const ClassDef& class_def) const { - return (class_def.static_values_off_ == 0) ? 0 : begin_ + class_def.static_values_off_; + return DataPointer<uint8_t>(class_def.static_values_off_); } const uint8_t* GetCallSiteEncodedValuesArray(const CallSiteIdItem& call_site_id) const { - return begin_ + call_site_id.data_off_; + return DataBegin() + call_site_id.data_off_; } static const TryItem* GetTryItems(const DexInstructionIterator& code_item_end, uint32_t offset); @@ -756,7 +746,9 @@ class DexFile { // Check that the offset is in bounds. // Note that although the specification says that 0 should be used if there // is no debug information, some applications incorrectly use 0xFFFFFFFF. - return (debug_info_off == 0 || debug_info_off >= size_) ? nullptr : begin_ + debug_info_off; + return (debug_info_off == 0 || debug_info_off >= data_size_) + ? nullptr + : DataBegin() + debug_info_off; } struct PositionInfo { @@ -787,21 +779,17 @@ class DexFile { static bool LineNumForPcCb(void* context, const PositionInfo& entry); const AnnotationsDirectoryItem* GetAnnotationsDirectory(const ClassDef& class_def) const { - return (class_def.annotations_off_ == 0) - ? nullptr - : reinterpret_cast<const AnnotationsDirectoryItem*>(begin_ + class_def.annotations_off_); + return DataPointer<AnnotationsDirectoryItem>(class_def.annotations_off_); } const AnnotationSetItem* GetClassAnnotationSet(const AnnotationsDirectoryItem* anno_dir) const { - return (anno_dir->class_annotations_off_ == 0) - ? nullptr - : reinterpret_cast<const AnnotationSetItem*>(begin_ + anno_dir->class_annotations_off_); + return DataPointer<AnnotationSetItem>(anno_dir->class_annotations_off_); } const FieldAnnotationsItem* GetFieldAnnotations(const AnnotationsDirectoryItem* anno_dir) const { return (anno_dir->fields_size_ == 0) - ? nullptr - : reinterpret_cast<const FieldAnnotationsItem*>(&anno_dir[1]); + ? nullptr + : reinterpret_cast<const FieldAnnotationsItem*>(&anno_dir[1]); } const MethodAnnotationsItem* GetMethodAnnotations(const AnnotationsDirectoryItem* anno_dir) @@ -828,33 +816,21 @@ class DexFile { } const AnnotationSetItem* GetFieldAnnotationSetItem(const FieldAnnotationsItem& anno_item) const { - uint32_t offset = anno_item.annotations_off_; - return (offset == 0) - ? nullptr - : reinterpret_cast<const AnnotationSetItem*>(begin_ + offset); + return DataPointer<AnnotationSetItem>(anno_item.annotations_off_); } const AnnotationSetItem* GetMethodAnnotationSetItem(const MethodAnnotationsItem& anno_item) const { - uint32_t offset = anno_item.annotations_off_; - return (offset == 0) - ? nullptr - : reinterpret_cast<const AnnotationSetItem*>(begin_ + offset); + return DataPointer<AnnotationSetItem>(anno_item.annotations_off_); } const AnnotationSetRefList* GetParameterAnnotationSetRefList( const ParameterAnnotationsItem* anno_item) const { - uint32_t offset = anno_item->annotations_off_; - return (offset == 0) - ? nullptr - : reinterpret_cast<const AnnotationSetRefList*>(begin_ + offset); + return DataPointer<AnnotationSetRefList>(anno_item->annotations_off_); } ALWAYS_INLINE const AnnotationItem* GetAnnotationItemAtOffset(uint32_t offset) const { - DCHECK_LE(offset, Size()); - return (offset == 0) - ? nullptr - : reinterpret_cast<const AnnotationItem*>(begin_ + offset); + return DataPointer<AnnotationItem>(offset); } const AnnotationItem* GetAnnotationItem(const AnnotationSetItem* set_item, uint32_t index) const { @@ -863,10 +839,7 @@ class DexFile { } const AnnotationSetItem* GetSetRefItemItem(const AnnotationSetRefItem* anno_item) const { - uint32_t offset = anno_item->annotations_off_; - return (offset == 0) - ? nullptr - : reinterpret_cast<const AnnotationSetItem*>(begin_ + offset); + return DataPointer<AnnotationSetItem>(anno_item->annotations_off_); } // Debug info opcodes and constants @@ -955,6 +928,20 @@ class DexFile { return size_; } + const uint8_t* DataBegin() const { + return data_begin_; + } + + size_t DataSize() const { + return data_size_; + } + + template <typename T> + const T* DataPointer(size_t offset) const { + DCHECK_LT(offset, DataSize()) << "Offset past end of data section"; + return (offset != 0u) ? reinterpret_cast<const T*>(DataBegin() + offset) : nullptr; + } + const OatDexFile* GetOatDexFile() const { return oat_dex_file_; } @@ -964,6 +951,11 @@ class DexFile { oat_dex_file_ = oat_dex_file; } + // Read MapItems and validate/set remaining offsets. + const DexFile::MapList* GetMapList() const { + return reinterpret_cast<const DexFile::MapList*>(DataBegin() + header_->map_off_); + } + // Utility methods for reading integral values from a buffer. static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth); static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right); @@ -971,8 +963,9 @@ class DexFile { static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right); // Recalculates the checksum of the dex file. Does not use the current value in the header. - uint32_t CalculateChecksum() const; + virtual uint32_t CalculateChecksum() const; static uint32_t CalculateChecksum(const uint8_t* begin, size_t size); + static uint32_t ChecksumMemoryRange(const uint8_t* begin, size_t size); // Returns a human-readable form of the method at an index. std::string PrettyMethod(uint32_t method_idx, bool with_signature = true) const; @@ -991,10 +984,14 @@ class DexFile { ALWAYS_INLINE const StandardDexFile* AsStandardDexFile() const; ALWAYS_INLINE const CompactDexFile* AsCompactDexFile() const; - bool HasAddress(const void* addr) const { + bool IsInMainSection(const void* addr) const { return Begin() <= addr && addr < Begin() + Size(); } + bool IsInDataSection(const void* addr) const { + return DataBegin() <= addr && addr < DataBegin() + DataSize(); + } + DexFileContainer* GetContainer() const { return container_.get(); } @@ -1005,6 +1002,8 @@ class DexFile { DexFile(const uint8_t* base, size_t size, + const uint8_t* data_begin, + size_t data_size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, @@ -1026,6 +1025,12 @@ class DexFile { // The size of the underlying memory allocation in bytes. const size_t size_; + // The base address of the data section (same as Begin() for standard dex). + const uint8_t* const data_begin_; + + // The size of the data section. + const size_t data_size_; + // Typically the dex file name when available, alternatively some identifying string. // // The ClassLinker will use this to match DexFiles the boot class diff --git a/runtime/dex/dex_file_loader.cc b/runtime/dex/dex_file_loader.cc index ccad19f22e..7dde0a42fd 100644 --- a/runtime/dex/dex_file_loader.cc +++ b/runtime/dex/dex_file_loader.cc @@ -222,6 +222,33 @@ std::unique_ptr<const DexFile> DexFileLoader::Open(const uint8_t* base, std::string* error_msg) const { return OpenCommon(base, size, + /*data_base*/ base, + /*data_size*/ size, + location, + location_checksum, + oat_dex_file, + verify, + verify_checksum, + error_msg, + /*container*/ nullptr, + /*verify_result*/ nullptr); +} + +std::unique_ptr<const DexFile> DexFileLoader::OpenWithDataSection( + const uint8_t* base, + size_t size, + const uint8_t* data_base, + size_t data_size, + const std::string& location, + uint32_t location_checksum, + const OatDexFile* oat_dex_file, + bool verify, + bool verify_checksum, + std::string* error_msg) const { + return OpenCommon(base, + size, + data_base, + data_size, location, location_checksum, oat_dex_file, @@ -278,6 +305,8 @@ bool DexFileLoader::OpenAll( std::unique_ptr<DexFile> DexFileLoader::OpenCommon(const uint8_t* base, size_t size, + const uint8_t* data_base, + size_t data_size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, @@ -291,11 +320,32 @@ std::unique_ptr<DexFile> DexFileLoader::OpenCommon(const uint8_t* base, } std::unique_ptr<DexFile> dex_file; if (StandardDexFile::IsMagicValid(base)) { - dex_file.reset( - new StandardDexFile(base, size, location, location_checksum, oat_dex_file, container)); + if (data_size != 0) { + CHECK_EQ(base, data_base) << "Unsupported for standard dex"; + } + dex_file.reset(new StandardDexFile(base, + size, + location, + location_checksum, + oat_dex_file, + container)); } else if (CompactDexFile::IsMagicValid(base)) { - dex_file.reset( - new CompactDexFile(base, size, location, location_checksum, oat_dex_file, container)); + if (data_base == nullptr) { + // TODO: Is there a clean way to support both an explicit data section and reading the one + // from the header. + CHECK_EQ(data_size, 0u); + const CompactDexFile::Header* const header = CompactDexFile::Header::At(base); + data_base = base + header->data_off_; + data_size = header->data_size_; + } + dex_file.reset(new CompactDexFile(base, + size, + data_base, + data_size, + location, + location_checksum, + oat_dex_file, + container)); } if (dex_file == nullptr) { *error_msg = StringPrintf("Failed to open dex file '%s' from memory: %s", location.c_str(), @@ -353,6 +403,8 @@ std::unique_ptr<const DexFile> DexFileLoader::OpenOneDexFileFromZip( VerifyResult verify_result; std::unique_ptr<const DexFile> dex_file = OpenCommon(map.data(), map.size(), + /*data_base*/ nullptr, + /*data_size*/ 0u, location, zip_entry->GetCrc32(), /*oat_dex_file*/ nullptr, diff --git a/runtime/dex/dex_file_loader.h b/runtime/dex/dex_file_loader.h index 05a51d09b3..508397cb00 100644 --- a/runtime/dex/dex_file_loader.h +++ b/runtime/dex/dex_file_loader.h @@ -120,6 +120,20 @@ class DexFileLoader { bool verify_checksum, std::string* error_msg) const; + // Open a dex file with a separate data section. + virtual std::unique_ptr<const DexFile> OpenWithDataSection( + const uint8_t* base, + size_t size, + const uint8_t* data_base, + size_t data_size, + const std::string& location, + uint32_t location_checksum, + const OatDexFile* oat_dex_file, + bool verify, + bool verify_checksum, + std::string* error_msg) const; + + // Opens all .dex files found in the memory map, guessing the container format based on file // extension. virtual bool OpenAll(const uint8_t* base, @@ -148,6 +162,8 @@ class DexFileLoader { static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base, size_t size, + const uint8_t* data_base, + size_t data_size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, diff --git a/runtime/dex/standard_dex_file.cc b/runtime/dex/standard_dex_file.cc index 52fdff303b..024f73b4e5 100644 --- a/runtime/dex/standard_dex_file.cc +++ b/runtime/dex/standard_dex_file.cc @@ -73,10 +73,7 @@ bool StandardDexFile::SupportsDefaultMethods() const { } uint32_t StandardDexFile::GetCodeItemSize(const DexFile::CodeItem& item) const { - DCHECK(HasAddress(&item)); - // TODO: Clean up this temporary code duplication with StandardDexFile. Eventually the - // implementations will differ. - DCHECK(HasAddress(&item)); + DCHECK(IsInDataSection(&item)); return reinterpret_cast<uintptr_t>(CodeItemDataAccessor(*this, &item).CodeItemDataEnd()) - reinterpret_cast<uintptr_t>(&item); } diff --git a/runtime/dex/standard_dex_file.h b/runtime/dex/standard_dex_file.h index 6437def4f5..94ef1f2a8e 100644 --- a/runtime/dex/standard_dex_file.h +++ b/runtime/dex/standard_dex_file.h @@ -92,6 +92,8 @@ class StandardDexFile : public DexFile { DexFileContainer* container) : DexFile(base, size, + /*data_begin*/ base, + /*data_size*/ size, location, location_checksum, oat_dex_file, diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index 9fd99057a1..307f7b96ed 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -1653,7 +1653,12 @@ OatFile::OatDexFile::OatDexFile(const OatFile* oat_file, if (lookup_table_data_ + TypeLookupTable::RawDataLength(num_class_defs) > GetOatFile()->End()) { LOG(WARNING) << "found truncated lookup table in " << dex_file_location_; } else { - lookup_table_ = TypeLookupTable::Open(dex_file_pointer_, lookup_table_data_, num_class_defs); + const uint8_t* dex_data = dex_file_pointer_; + // TODO: Clean this up to create the type lookup table after the dex file has been created? + if (CompactDexFile::IsMagicValid(dex_header->magic_)) { + dex_data += dex_header->data_off_; + } + lookup_table_ = TypeLookupTable::Open(dex_data, lookup_table_data_, num_class_defs); } } } @@ -1733,9 +1738,17 @@ const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_fi size_t hash) { const OatFile::OatDexFile* oat_dex_file = dex_file.GetOatDexFile(); DCHECK_EQ(ComputeModifiedUtf8Hash(descriptor), hash); + bool used_lookup_table = false; + const DexFile::ClassDef* lookup_table_classdef = nullptr; if (LIKELY((oat_dex_file != nullptr) && (oat_dex_file->GetTypeLookupTable() != nullptr))) { + used_lookup_table = true; const uint32_t class_def_idx = oat_dex_file->GetTypeLookupTable()->Lookup(descriptor, hash); - return (class_def_idx != dex::kDexNoIndex) ? &dex_file.GetClassDef(class_def_idx) : nullptr; + lookup_table_classdef = (class_def_idx != dex::kDexNoIndex) + ? &dex_file.GetClassDef(class_def_idx) + : nullptr; + if (!kIsDebugBuild) { + return lookup_table_classdef; + } } // Fast path for rare no class defs case. const uint32_t num_class_defs = dex_file.NumClassDefs(); @@ -1745,7 +1758,11 @@ const DexFile::ClassDef* OatFile::OatDexFile::FindClassDef(const DexFile& dex_fi const DexFile::TypeId* type_id = dex_file.FindTypeId(descriptor); if (type_id != nullptr) { dex::TypeIndex type_idx = dex_file.GetIndexForTypeId(*type_id); - return dex_file.FindClassDef(type_idx); + const DexFile::ClassDef* found_class_def = dex_file.FindClassDef(type_idx); + if (kIsDebugBuild && used_lookup_table) { + DCHECK_EQ(found_class_def, lookup_table_classdef); + } + return found_class_def; } return nullptr; } diff --git a/runtime/type_lookup_table.cc b/runtime/type_lookup_table.cc index 6eb3d83631..649a4f9547 100644 --- a/runtime/type_lookup_table.cc +++ b/runtime/type_lookup_table.cc @@ -66,7 +66,7 @@ std::unique_ptr<TypeLookupTable> TypeLookupTable::Open(const uint8_t* dex_file_p } TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage) - : dex_file_begin_(dex_file.Begin()), + : dex_data_begin_(dex_file.DataBegin()), raw_data_length_(RawDataLength(dex_file.NumClassDefs())), mask_(CalculateMask(dex_file.NumClassDefs())), entries_(storage != nullptr ? reinterpret_cast<Entry*>(storage) : new Entry[mask_ + 1]), @@ -106,7 +106,7 @@ TypeLookupTable::TypeLookupTable(const DexFile& dex_file, uint8_t* storage) TypeLookupTable::TypeLookupTable(const uint8_t* dex_file_pointer, const uint8_t* raw_data, uint32_t num_class_defs) - : dex_file_begin_(dex_file_pointer), + : dex_data_begin_(dex_file_pointer), raw_data_length_(RawDataLength(num_class_defs)), mask_(CalculateMask(num_class_defs)), entries_(reinterpret_cast<Entry*>(const_cast<uint8_t*>(raw_data))), diff --git a/runtime/type_lookup_table.h b/runtime/type_lookup_table.h index 6a6f47fba2..50c93ad9f0 100644 --- a/runtime/type_lookup_table.h +++ b/runtime/type_lookup_table.h @@ -43,7 +43,7 @@ class TypeLookupTable { // Method search class_def_idx by class descriptor and it's hash. // If no data found then the method returns dex::kDexNoIndex. - ALWAYS_INLINE uint32_t Lookup(const char* str, uint32_t hash) const { + uint32_t Lookup(const char* str, uint32_t hash) const { uint32_t pos = hash & GetSizeMask(); // Thanks to special insertion algorithm, the element at position pos can be empty or start of // bucket. @@ -127,8 +127,8 @@ class TypeLookupTable { uint32_t num_class_defs); bool IsStringsEquals(const char* str, uint32_t str_offset) const { - const uint8_t* ptr = dex_file_begin_ + str_offset; - CHECK(dex_file_begin_ != nullptr); + const uint8_t* ptr = dex_data_begin_ + str_offset; + CHECK(dex_data_begin_ != nullptr); // Skip string length. DecodeUnsignedLeb128(&ptr); return CompareModifiedUtf8ToModifiedUtf8AsUtf16CodePointValues( @@ -160,7 +160,7 @@ class TypeLookupTable { // Find the last entry in a chain. uint32_t FindLastEntryInBucket(uint32_t cur_pos) const; - const uint8_t* dex_file_begin_; + const uint8_t* dex_data_begin_; const uint32_t raw_data_length_; const uint32_t mask_; std::unique_ptr<Entry[]> entries_; diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc index cab91dfe76..36ebb17f4f 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -48,10 +48,12 @@ bool VdexFile::Header::IsVersionValid() const { VdexFile::Header::Header(uint32_t number_of_dex_files, uint32_t dex_size, + uint32_t dex_shared_data_size, uint32_t verifier_deps_size, uint32_t quickening_info_size) : number_of_dex_files_(number_of_dex_files), dex_size_(dex_size), + dex_shared_data_size_(dex_shared_data_size), verifier_deps_size_(verifier_deps_size), quickening_info_size_(quickening_info_size) { memcpy(magic_, kVdexMagic, sizeof(kVdexMagic)); @@ -183,14 +185,17 @@ bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_ // TODO: Supply the location information for a vdex file. static constexpr char kVdexLocation[] = ""; std::string location = DexFileLoader::GetMultiDexLocation(i, kVdexLocation); - std::unique_ptr<const DexFile> dex(dex_file_loader.Open(dex_file_start, - size, - location, - GetLocationChecksum(i), - nullptr /*oat_dex_file*/, - false /*verify*/, - false /*verify_checksum*/, - error_msg)); + std::unique_ptr<const DexFile> dex(dex_file_loader.OpenWithDataSection( + dex_file_start, + size, + /*data_base*/ nullptr, + /*data_size*/ 0u, + location, + GetLocationChecksum(i), + nullptr /*oat_dex_file*/, + false /*verify*/, + false /*verify_checksum*/, + error_msg)); if (dex == nullptr) { return false; } diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h index 4e45128420..e8d66ace8e 100644 --- a/runtime/vdex_file.h +++ b/runtime/vdex_file.h @@ -54,6 +54,7 @@ class VdexFile { public: Header(uint32_t number_of_dex_files_, uint32_t dex_size, + uint32_t dex_shared_data_size, uint32_t verifier_deps_size, uint32_t quickening_info_size); @@ -64,6 +65,7 @@ class VdexFile { bool IsValid() const { return IsMagicValid() && IsVersionValid(); } uint32_t GetDexSize() const { return dex_size_; } + uint32_t GetDexSharedDataSize() const { return dex_shared_data_size_; } uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; } uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; } uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; } @@ -72,6 +74,7 @@ class VdexFile { return sizeof(Header) + GetSizeOfChecksumsSection() + GetDexSize() + + GetDexSharedDataSize() + GetVerifierDepsSize() + GetQuickeningInfoSize(); } @@ -84,13 +87,14 @@ class VdexFile { private: static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' }; - // Last update: Use efficient encoding for compact dex code item fields - static constexpr uint8_t kVdexVersion[] = { '0', '1', '5', '\0' }; + // Last update: Separate section for compact dex data. + static constexpr uint8_t kVdexVersion[] = { '0', '1', '6', '\0' }; uint8_t magic_[4]; uint8_t version_[4]; uint32_t number_of_dex_files_; uint32_t dex_size_; + uint32_t dex_shared_data_size_; uint32_t verifier_deps_size_; uint32_t quickening_info_size_; @@ -172,7 +176,8 @@ class VdexFile { ArrayRef<const uint8_t> GetVerifierDepsData() const { return ArrayRef<const uint8_t>( - DexBegin() + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize()); + DexBegin() + GetHeader().GetDexSize() + GetHeader().GetDexSharedDataSize(), + GetHeader().GetVerifierDepsSize()); } ArrayRef<const uint8_t> GetQuickeningInfo() const { |