Handle de-duped CodeItems in dexlayout
De-duplicated (shared) CodeItems were added to the layout structures
multiple times, resulting in multiple update of offsets and
uninitialized data in the resulting dex files.
Bug: 67024225
Test: make test-art-host
Change-Id: I76ffd2cb52fe72eab3fb0dbf6ad8607951cee595
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 6b0b0f8..ffd1136 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1794,6 +1794,10 @@
}
}
+ // Removing duplicate CodeItems may expose other issues with downstream
+ // optimizations such as quickening. But we need to ensure at least the weak
+ // forms of it currently in use do not break layout optimizations.
+ std::map<dex_ir::CodeItem*, uint32_t> original_code_item_offset;
// Total_diff includes diffs generated by clinits, executed, and non-executed methods.
int32_t total_diff = 0;
// The relative placement has no effect on correctness; it is used to ensure
@@ -1812,11 +1816,22 @@
dex_ir::CodeItem* code_item = method->GetCodeItem();
if (code_item != nullptr &&
code_items_set.find(code_item) != code_items_set.end()) {
- diff += UnsignedLeb128Size(code_item_offset)
- - UnsignedLeb128Size(code_item->GetOffset());
- code_item->SetOffset(code_item_offset);
- code_item_offset +=
- RoundUp(code_item->GetSize(), kDexCodeItemAlignment);
+ // Compute where the CodeItem was originally laid out.
+ uint32_t original_offset = code_item->GetOffset();
+ auto it = original_code_item_offset.find(code_item);
+ if (it != original_code_item_offset.end()) {
+ original_offset = it->second;
+ } else {
+ original_code_item_offset[code_item] = code_item->GetOffset();
+ // Assign the new offset and move the pointer to allocate space.
+ code_item->SetOffset(code_item_offset);
+ code_item_offset +=
+ RoundUp(code_item->GetSize(), kDexCodeItemAlignment);
+ }
+ // Update the size of the encoded methods to reflect that the offset difference
+ // may have changed the ULEB128 length.
+ diff +=
+ UnsignedLeb128Size(code_item->GetOffset()) - UnsignedLeb128Size(original_offset);
}
}
}