diff options
-rw-r--r-- | dexlayout/dex_ir.h | 11 | ||||
-rw-r--r-- | dexlayout/dex_ir_builder.cc | 5 | ||||
-rw-r--r-- | dexlayout/dex_writer.cc | 10 | ||||
-rw-r--r-- | dexlayout/dexlayout_test.cc | 41 |
4 files changed, 66 insertions, 1 deletions
diff --git a/dexlayout/dex_ir.h b/dexlayout/dex_ir.h index 61a4eae9b1..8421774104 100644 --- a/dexlayout/dex_ir.h +++ b/dexlayout/dex_ir.h @@ -396,6 +396,14 @@ class Collections { eagerly_assign_offsets_ = eagerly_assign_offsets; } + void SetLinkData(std::vector<uint8_t>&& link_data) { + link_data_ = std::move(link_data); + } + + const std::vector<uint8_t>& LinkData() const { + return link_data_; + } + private: EncodedValue* ReadEncodedValue(const DexFile& dex_file, const uint8_t** data); EncodedValue* ReadEncodedValue(const DexFile& dex_file, @@ -452,6 +460,9 @@ class Collections { uint32_t map_list_offset_ = 0; + // Link data. + std::vector<uint8_t> link_data_; + // If we eagerly assign offsets during IR building or later after layout. Must be false if // changing the layout is enabled. bool eagerly_assign_offsets_; diff --git a/dexlayout/dex_ir_builder.cc b/dexlayout/dex_ir_builder.cc index 924dfe076a..1fd963fe22 100644 --- a/dexlayout/dex_ir_builder.cc +++ b/dexlayout/dex_ir_builder.cc @@ -80,6 +80,11 @@ Header* DexIrBuilder(const DexFile& dex_file, bool eagerly_assign_offsets) { // Sort the vectors by the map order (same order as the file). collections.SortVectorsByMapOrder(); + // 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_)); + return header; } diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc index c85bca0d92..1fac2359b0 100644 --- a/dexlayout/dex_writer.cc +++ b/dexlayout/dex_writer.cc @@ -878,7 +878,15 @@ void DexWriter::WriteMemMap() { } } - // TODO: Write link data? + // Write link data if it exists. + const std::vector<uint8_t>& link_data = collection.LinkData(); + if (link_data.size() > 0) { + CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size())); + if (compute_offsets_) { + header_->SetLinkOffset(offset); + } + offset += Write(&link_data[0], link_data.size(), header_->LinkOffset()); + } // Write header last. if (compute_offsets_) { diff --git a/dexlayout/dexlayout_test.cc b/dexlayout/dexlayout_test.cc index c4f7accc8c..19c9038ee6 100644 --- a/dexlayout/dexlayout_test.cc +++ b/dexlayout/dexlayout_test.cc @@ -732,4 +732,45 @@ TEST_F(DexLayoutTest, CodeItemOverrun) { dexlayout_args)); } +// Test that link data is written out (or at least the header is updated). +TEST_F(DexLayoutTest, LinkData) { + ScratchFile temp_dex; + size_t file_size = 0; + MutateDexFile(temp_dex.GetFile(), GetTestDexFileName("ManyMethods"), [&] (DexFile* dex) { + DexFile::Header& header = const_cast<DexFile::Header&>(dex->GetHeader()); + header.link_off_ = header.file_size_; + header.link_size_ = 16 * KB; + header.file_size_ += header.link_size_; + file_size = header.file_size_; + }); + TEMP_FAILURE_RETRY(temp_dex.GetFile()->SetLength(file_size)); + + std::string error_msg; + + ScratchFile tmp_file; + const std::string& tmp_name = tmp_file.GetFilename(); + size_t tmp_last_slash = tmp_name.rfind('/'); + std::string tmp_dir = tmp_name.substr(0, tmp_last_slash + 1); + ScratchFile profile_file; + + std::vector<std::string> dexlayout_args = + { "-i", + "-v", + "-w", tmp_dir, + "-o", tmp_name, + "-p", profile_file.GetFilename(), + temp_dex.GetFilename() + }; + // -v makes sure that the layout did not corrupt the dex file. + ASSERT_TRUE(DexLayoutExec(&temp_dex, + /*dex_filename*/ nullptr, + &profile_file, + dexlayout_args)); + + std::string output_dex = temp_dex.GetFilename() + ".new"; + std::vector<std::string> rm_exec_argv = + { "/bin/rm", output_dex }; + ASSERT_TRUE(::art::Exec(rm_exec_argv, &error_msg)); +} + } // namespace art |