Fix method handles using wrong section
For compact dex, the method handles were using offsets relative to
data section instead of main section. Fixed this code and the map
list offset logic in InitializeSectionsFromMapList.
Test: test/run-test --always-clean --dex2oat-jobs 4 --host --prebuild --compact-dex-level fast --optimizing --no-relocate --runtime-option -Xcheck:jni 979-const-method-handle
Bug: 63756964
Change-Id: I9e6ddfd77da99ae1aedef7591536be190ff60904
diff --git a/dexlayout/compact_dex_writer.cc b/dexlayout/compact_dex_writer.cc
index ef31c3f..0580f16 100644
--- a/dexlayout/compact_dex_writer.cc
+++ b/dexlayout/compact_dex_writer.cc
@@ -285,6 +285,7 @@
}
void CompactDexWriter::Write(DexContainer* output) {
+ CHECK(compute_offsets_);
CHECK(output->IsCompactDexContainer());
Container* const container = down_cast<Container*>(output);
// For now, use the same stream for both data and metadata.
diff --git a/dexlayout/dex_writer.cc b/dexlayout/dex_writer.cc
index 67d0f9a..4181e9c 100644
--- a/dexlayout/dex_writer.cc
+++ b/dexlayout/dex_writer.cc
@@ -683,19 +683,17 @@
uint32_t DexWriter::WriteMapItems(Stream* stream, MapItemQueue* queue) {
// All the sections should already have been added.
- uint16_t uint16_buffer[2];
- uint32_t uint32_buffer[2];
- uint16_buffer[1] = 0;
- uint32_buffer[0] = queue->size();
+ const uint32_t map_list_size = queue->size();
const uint32_t start = stream->Tell();
- stream->Write(uint32_buffer, sizeof(uint32_t));
+ stream->Write(&map_list_size, sizeof(map_list_size));
while (!queue->empty()) {
- const MapItem& map_item = queue->top();
- uint16_buffer[0] = map_item.type_;
- uint32_buffer[0] = map_item.size_;
- uint32_buffer[1] = map_item.offset_;
- stream->Write(uint16_buffer, 2 * sizeof(uint16_t));
- stream->Write(uint32_buffer, 2 * sizeof(uint32_t));
+ const MapItem& item = queue->top();
+ DexFile::MapItem map_item;
+ map_item.type_ = item.type_;
+ map_item.size_ = item.size_;
+ map_item.offset_ = item.offset_;
+ map_item.unused_ = 0u;
+ stream->Write(&map_item, sizeof(map_item));
queue->pop();
}
return stream->Tell() - start;
diff --git a/runtime/dex/dex_file.cc b/runtime/dex/dex_file.cc
index 6ec997c..f0209f7 100644
--- a/runtime/dex/dex_file.cc
+++ b/runtime/dex/dex_file.cc
@@ -157,14 +157,14 @@
void DexFile::InitializeSectionsFromMapList() {
const MapList* map_list = reinterpret_cast<const MapList*>(DataBegin() + header_->map_off_);
- if (header_->map_off_ == 0 || header_->map_off_ > size_) {
+ if (header_->map_off_ == 0 || header_->map_off_ > DataSize()) {
// Bad offset. The dex file verifier runs after this method and will reject the file.
return;
}
const size_t count = map_list->size_;
size_t map_limit = header_->map_off_ + count * sizeof(MapItem);
- if (header_->map_off_ >= map_limit || map_limit > size_) {
+ if (header_->map_off_ >= map_limit || map_limit > DataSize()) {
// Overflow or out out of bounds. The dex file verifier runs after
// this method and will reject the file as it is malformed.
return;
@@ -173,10 +173,10 @@
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*>(DataBegin() + map_item.offset_);
+ method_handles_ = reinterpret_cast<const MethodHandleItem*>(Begin() + map_item.offset_);
num_method_handles_ = map_item.size_;
} else if (map_item.type_ == kDexTypeCallSiteIdItem) {
- call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(DataBegin() + map_item.offset_);
+ call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(Begin() + 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 ef25797..7e2fe98 100644
--- a/runtime/dex/dex_file.h
+++ b/runtime/dex/dex_file.h
@@ -138,9 +138,6 @@
uint16_t unused_;
uint32_t size_;
uint32_t offset_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MapItem);
};
struct MapList {