Prevent dexlayout from moving code items if preceded by class data.
Class data has uleb encoded offsets to the code item, and moving code
items will change the size of the class data, which would in turn affect
the code item offsets if they precede the code items.
For now, make it so that dexlayout does not move the code items at all
in this case. A better fix would be to swap the order of the sections in
dexlayout, but that can be done in a future CL.
Unit test to follow.
Bug: 35855748
Test: mm test-art-host
Change-Id: Ica6da1e5e951cf0003fc9793f13ad10b74004eb9
diff --git a/dexlayout/dexlayout.cc b/dexlayout/dexlayout.cc
index 22619b9..4aa8b82 100644
--- a/dexlayout/dexlayout.cc
+++ b/dexlayout/dexlayout.cc
@@ -1529,10 +1529,18 @@
// NOTE: If the section following the code items is byte aligned, the last code item is left in
// place to preserve alignment. Layout needs an overhaul to handle movement of other sections.
int32_t DexLayout::LayoutCodeItems(std::vector<dex_ir::ClassData*> new_class_data_order) {
+ // Do not move code items if class data section precedes code item section.
+ // ULEB encoding is variable length, causing problems determining the offset of the code items.
+ // TODO: We should swap the order of these sections in the future to avoid this issue.
+ uint32_t class_data_offset = header_->GetCollections().ClassDatasOffset();
+ uint32_t code_item_offset = header_->GetCollections().CodeItemsOffset();
+ if (class_data_offset < code_item_offset) {
+ return 0;
+ }
+
// Find the last code item so we can leave it in place if the next section is not 4 byte aligned.
std::unordered_set<dex_ir::CodeItem*> visited_code_items;
- uint32_t offset = header_->GetCollections().CodeItemsOffset();
- bool is_code_item_aligned = IsNextSectionCodeItemAligned(offset);
+ bool is_code_item_aligned = IsNextSectionCodeItemAligned(code_item_offset);
if (!is_code_item_aligned) {
dex_ir::CodeItem* last_code_item = nullptr;
for (auto& code_item_pair : header_->GetCollections().CodeItems()) {
@@ -1552,18 +1560,18 @@
dex_ir::CodeItem* code_item = method->GetCodeItem();
if (code_item != nullptr && visited_code_items.find(code_item) == visited_code_items.end()) {
visited_code_items.insert(code_item);
- diff += UnsignedLeb128Size(offset) - UnsignedLeb128Size(code_item->GetOffset());
- code_item->SetOffset(offset);
- offset += RoundUp(code_item->GetSize(), kDexCodeItemAlignment);
+ diff += UnsignedLeb128Size(code_item_offset) - UnsignedLeb128Size(code_item->GetOffset());
+ code_item->SetOffset(code_item_offset);
+ code_item_offset += RoundUp(code_item->GetSize(), kDexCodeItemAlignment);
}
}
for (auto& method : *class_data->VirtualMethods()) {
dex_ir::CodeItem* code_item = method->GetCodeItem();
if (code_item != nullptr && visited_code_items.find(code_item) == visited_code_items.end()) {
visited_code_items.insert(code_item);
- diff += UnsignedLeb128Size(offset) - UnsignedLeb128Size(code_item->GetOffset());
- code_item->SetOffset(offset);
- offset += RoundUp(code_item->GetSize(), kDexCodeItemAlignment);
+ diff += UnsignedLeb128Size(code_item_offset) - UnsignedLeb128Size(code_item->GetOffset());
+ code_item->SetOffset(code_item_offset);
+ code_item_offset += RoundUp(code_item->GetSize(), kDexCodeItemAlignment);
}
}
}