summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dexlayout/dex_ir.h11
-rw-r--r--dexlayout/dex_ir_builder.cc5
-rw-r--r--dexlayout/dex_writer.cc10
-rw-r--r--dexlayout/dexlayout_test.cc41
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