ART: Add DEX support for MethodHandle and CallSite info.
Adds new DEX file map items for CallSiteIds and MethodHandles.
Initializes CallSiteIds and MethodHandles from the DEX file map_list.
Bug: 33191717,30550796
Test: m test-art-host-gtest-dex_file_verifier_test
Change-Id: I3ad9c7342b661c3f6a8264709412650eee6bde01
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index f59420d..02ba33c 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -497,9 +497,14 @@
method_ids_(reinterpret_cast<const MethodId*>(base + header_->method_ids_off_)),
proto_ids_(reinterpret_cast<const ProtoId*>(base + header_->proto_ids_off_)),
class_defs_(reinterpret_cast<const ClassDef*>(base + header_->class_defs_off_)),
+ method_handles_(nullptr),
+ num_method_handles_(0),
+ call_site_ids_(nullptr),
+ num_call_site_ids_(0),
oat_dex_file_(oat_dex_file) {
CHECK(begin_ != nullptr) << GetLocation();
CHECK_GT(size_, 0U) << GetLocation();
+ InitializeSectionsFromMapList();
}
DexFile::~DexFile() {
@@ -540,6 +545,29 @@
return true;
}
+void DexFile::InitializeSectionsFromMapList() {
+ const MapList* map_list = reinterpret_cast<const MapList*>(begin_ + header_->map_off_);
+ 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_) {
+ // Overflow or out out of bounds. The dex file verifier runs after
+ // this method and will reject the file as it is malformed.
+ return;
+ }
+
+ 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*>(begin_ + map_item.offset_);
+ num_method_handles_ = map_item.size_;
+ } else if (map_item.type_ == kDexTypeCallSiteIdItem) {
+ call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(begin_ + map_item.offset_);
+ num_call_site_ids_ = map_item.size_;
+ }
+ }
+}
+
bool DexFile::IsMagicValid(const uint8_t* magic) {
return (memcmp(magic, kDexMagic, sizeof(kDexMagic)) == 0);
}
@@ -1339,24 +1367,20 @@
}
}
-EncodedStaticFieldValueIterator::EncodedStaticFieldValueIterator(const DexFile& dex_file,
- const DexFile::ClassDef& class_def)
+EncodedArrayValueIterator::EncodedArrayValueIterator(const DexFile& dex_file,
+ const uint8_t* array_data)
: dex_file_(dex_file),
array_size_(),
pos_(-1),
+ ptr_(array_data),
type_(kByte) {
- ptr_ = dex_file_.GetEncodedStaticFieldValuesArray(class_def);
- if (ptr_ == nullptr) {
- array_size_ = 0;
- } else {
- array_size_ = DecodeUnsignedLeb128(&ptr_);
- }
+ array_size_ = (ptr_ != nullptr) ? DecodeUnsignedLeb128(&ptr_) : 0;
if (array_size_ > 0) {
Next();
}
}
-void EncodedStaticFieldValueIterator::Next() {
+void EncodedArrayValueIterator::Next() {
pos_++;
if (pos_ >= array_size_) {
return;
@@ -1396,6 +1420,8 @@
break;
case kString:
case kType:
+ case kMethodType:
+ case kMethodHandle:
jval_.i = DexFile::ReadUnsignedInt(ptr_, value_arg, false);
break;
case kField: