diff options
| author | David Brazdil <dbrazdil@google.com> | 2018-10-24 12:34:06 +0000 |
|---|---|---|
| committer | David Brazdil <dbrazdil@google.com> | 2018-10-24 12:37:49 +0000 |
| commit | d9a0437b0d6cb1438bf21284a2502cbfe293db06 (patch) | |
| tree | 3bb8a93f499ac537d445e90533598571f3d2d120 /libdexfile | |
| parent | fd2aa2bf72563870c9261f248f992a20ac4837a8 (diff) | |
| download | art-d9a0437b0d6cb1438bf21284a2502cbfe293db06.tar.gz art-d9a0437b0d6cb1438bf21284a2502cbfe293db06.tar.bz2 art-d9a0437b0d6cb1438bf21284a2502cbfe293db06.zip | |
Revert "Add dex item for hiddenapi flags"
This reverts commit 0dbc363f32d075017e1c4fb5e17715e3f12d0157.
Reason for revert: marlin running out of space
Change-Id: I80218af6408812b639b7c807bf8cb2a1d5239d94
Diffstat (limited to 'libdexfile')
| -rw-r--r-- | libdexfile/dex/class_accessor-inl.h | 80 | ||||
| -rw-r--r-- | libdexfile/dex/class_accessor.h | 60 | ||||
| -rw-r--r-- | libdexfile/dex/dex_file.cc | 31 | ||||
| -rw-r--r-- | libdexfile/dex/dex_file.h | 44 | ||||
| -rw-r--r-- | libdexfile/dex/dex_file_verifier.cc | 118 | ||||
| -rw-r--r-- | libdexfile/dex/dex_file_verifier.h | 1 | ||||
| -rw-r--r-- | libdexfile/dex/hidden_api_access_flags.h | 93 | ||||
| -rw-r--r-- | libdexfile/dex/modifiers.h | 5 |
8 files changed, 171 insertions, 261 deletions
diff --git a/libdexfile/dex/class_accessor-inl.h b/libdexfile/dex/class_accessor-inl.h index 40bca564ae..21db2cf2be 100644 --- a/libdexfile/dex/class_accessor-inl.h +++ b/libdexfile/dex/class_accessor-inl.h @@ -28,54 +28,34 @@ namespace art { inline ClassAccessor::ClassAccessor(const ClassIteratorData& data) : ClassAccessor(data.dex_file_, data.class_def_idx_) {} -inline ClassAccessor::ClassAccessor(const DexFile& dex_file, - const DexFile::ClassDef& class_def, - bool parse_hiddenapi_class_data) - : ClassAccessor(dex_file, - dex_file.GetClassData(class_def), - dex_file.GetIndexForClassDef(class_def), - parse_hiddenapi_class_data) {} +inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const DexFile::ClassDef& class_def) + : ClassAccessor(dex_file, dex_file.GetIndexForClassDef(class_def)) {} inline ClassAccessor::ClassAccessor(const DexFile& dex_file, uint32_t class_def_index) - : ClassAccessor(dex_file, dex_file.GetClassDef(class_def_index)) {} + : ClassAccessor(dex_file, + dex_file.GetClassData(dex_file.GetClassDef(class_def_index)), + class_def_index) {} inline ClassAccessor::ClassAccessor(const DexFile& dex_file, const uint8_t* class_data, - uint32_t class_def_index, - bool parse_hiddenapi_class_data) + uint32_t class_def_index) : dex_file_(dex_file), class_def_index_(class_def_index), ptr_pos_(class_data), - hiddenapi_ptr_pos_(nullptr), num_static_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u), num_instance_fields_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u), num_direct_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u), - num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) { - if (parse_hiddenapi_class_data && class_def_index != DexFile::kDexNoIndex32) { - const DexFile::HiddenapiClassData* hiddenapi_class_data = dex_file.GetHiddenapiClassData(); - if (hiddenapi_class_data != nullptr) { - hiddenapi_ptr_pos_ = hiddenapi_class_data->GetFlagsPointer(class_def_index); - } - } -} + num_virtual_methods_(ptr_pos_ != nullptr ? DecodeUnsignedLeb128(&ptr_pos_) : 0u) {} inline void ClassAccessor::Method::Read() { index_ += DecodeUnsignedLeb128(&ptr_pos_); access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); code_off_ = DecodeUnsignedLeb128(&ptr_pos_); - if (hiddenapi_ptr_pos_ != nullptr) { - hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_); - DCHECK(HiddenApiAccessFlags::AreValidFlags(hiddenapi_flags_)); - } } inline void ClassAccessor::Field::Read() { index_ += DecodeUnsignedLeb128(&ptr_pos_); access_flags_ = DecodeUnsignedLeb128(&ptr_pos_); - if (hiddenapi_ptr_pos_ != nullptr) { - hiddenapi_flags_ = DecodeUnsignedLeb128(&hiddenapi_ptr_pos_); - DCHECK(HiddenApiAccessFlags::AreValidFlags(hiddenapi_flags_)); - } } template <typename DataType, typename Visitor> @@ -98,12 +78,12 @@ inline void ClassAccessor::VisitFieldsAndMethods( const InstanceFieldVisitor& instance_field_visitor, const DirectMethodVisitor& direct_method_visitor, const VirtualMethodVisitor& virtual_method_visitor) const { - Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_); + Field field(dex_file_, ptr_pos_); VisitMembers(num_static_fields_, static_field_visitor, &field); field.NextSection(); VisitMembers(num_instance_fields_, instance_field_visitor, &field); - Method method(dex_file_, field.ptr_pos_, field.hiddenapi_ptr_pos_, /*is_static_or_direct*/ true); + Method method(dex_file_, field.ptr_pos_, /*is_static_or_direct*/ true); VisitMembers(num_direct_methods_, direct_method_visitor, &method); method.NextSection(); VisitMembers(num_virtual_methods_, virtual_method_visitor, &method); @@ -151,43 +131,19 @@ inline const DexFile::CodeItem* ClassAccessor::Method::GetCodeItem() const { inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFieldsInternal(size_t count) const { - return { - DataIterator<Field>(dex_file_, - 0u, - num_static_fields_, - count, - ptr_pos_, - hiddenapi_ptr_pos_), - DataIterator<Field>(dex_file_, - count, - num_static_fields_, - count, - // The following pointers are bogus but unused in the `end` iterator. - ptr_pos_, - hiddenapi_ptr_pos_) }; + return { DataIterator<Field>(dex_file_, 0u, num_static_fields_, count, ptr_pos_), + DataIterator<Field>(dex_file_, count, num_static_fields_, count, ptr_pos_) }; } // Return an iteration range for the first <count> methods. inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> ClassAccessor::GetMethodsInternal(size_t count) const { // Skip over the fields. - Field field(dex_file_, ptr_pos_, hiddenapi_ptr_pos_); + Field field(dex_file_, ptr_pos_); VisitMembers(NumFields(), VoidFunctor(), &field); // Return the iterator pair. - return { - DataIterator<Method>(dex_file_, - 0u, - num_direct_methods_, - count, - field.ptr_pos_, - field.hiddenapi_ptr_pos_), - DataIterator<Method>(dex_file_, - count, - num_direct_methods_, - count, - // The following pointers are bogus but unused in the `end` iterator. - field.ptr_pos_, - field.hiddenapi_ptr_pos_) }; + return { DataIterator<Method>(dex_file_, 0u, num_direct_methods_, count, field.ptr_pos_), + DataIterator<Method>(dex_file_, count, num_direct_methods_, count, field.ptr_pos_) }; } inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Field>> ClassAccessor::GetFields() @@ -225,6 +181,14 @@ inline IterationRange<ClassAccessor::DataIterator<ClassAccessor::Method>> return { std::next(methods.begin(), NumDirectMethods()), methods.end() }; } +inline void ClassAccessor::Field::UnHideAccessFlags() const { + DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ false); +} + +inline void ClassAccessor::Method::UnHideAccessFlags() const { + DexFile::UnHideAccessFlags(const_cast<uint8_t*>(ptr_pos_), GetAccessFlags(), /*is_method*/ true); +} + inline dex::TypeIndex ClassAccessor::GetClassIdx() const { return dex_file_.GetClassDef(class_def_index_).class_idx_; } diff --git a/libdexfile/dex/class_accessor.h b/libdexfile/dex/class_accessor.h index e9c1a82c54..d40577f31f 100644 --- a/libdexfile/dex/class_accessor.h +++ b/libdexfile/dex/class_accessor.h @@ -20,6 +20,7 @@ #include "base/utils.h" #include "code_item_accessors.h" #include "dex_file.h" +#include "hidden_api_access_flags.h" #include "invoke_type.h" #include "method_reference.h" #include "modifiers.h" @@ -34,20 +35,22 @@ class ClassAccessor { class BaseItem { public: explicit BaseItem(const DexFile& dex_file, - const uint8_t* ptr_pos, - const uint8_t* hiddenapi_ptr_pos) - : dex_file_(dex_file), ptr_pos_(ptr_pos), hiddenapi_ptr_pos_(hiddenapi_ptr_pos) {} + const uint8_t* ptr_pos) : dex_file_(dex_file), ptr_pos_(ptr_pos) {} uint32_t GetIndex() const { return index_; } - uint32_t GetAccessFlags() const { + uint32_t GetRawAccessFlags() const { return access_flags_; } - uint32_t GetHiddenapiFlags() const { - return hiddenapi_flags_; + uint32_t GetAccessFlags() const { + return HiddenApiAccessFlags::RemoveFromDex(access_flags_); + } + + HiddenApiAccessFlags::ApiList DecodeHiddenAccessFlags() const { + return HiddenApiAccessFlags::DecodeFromDex(access_flags_); } bool IsFinal() const { @@ -63,21 +66,19 @@ class ClassAccessor { } bool MemberIsNative() const { - return GetAccessFlags() & kAccNative; + return GetRawAccessFlags() & kAccNative; } bool MemberIsFinal() const { - return GetAccessFlags() & kAccFinal; + return GetRawAccessFlags() & kAccFinal; } protected: // Internal data pointer for reading. const DexFile& dex_file_; const uint8_t* ptr_pos_ = nullptr; - const uint8_t* hiddenapi_ptr_pos_ = nullptr; uint32_t index_ = 0u; uint32_t access_flags_ = 0u; - uint32_t hiddenapi_flags_ = 0u; }; // A decoded version of the method of a class_data_item. @@ -106,13 +107,14 @@ class ClassAccessor { return is_static_or_direct_; } + // Unhide the hidden API access flags at the iterator position. TODO: Deprecate. + void UnHideAccessFlags() const; + private: - Method(const DexFile& dex_file, - const uint8_t* ptr_pos, - const uint8_t* hiddenapi_ptr_pos = nullptr, - bool is_static_or_direct = true) - : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos), - is_static_or_direct_(is_static_or_direct) {} + explicit Method(const DexFile& dex_file, + const uint8_t* ptr_pos, + bool is_static_or_direct = true) + : BaseItem(dex_file, ptr_pos), is_static_or_direct_(is_static_or_direct) {} void Read(); @@ -148,15 +150,16 @@ class ClassAccessor { // A decoded version of the field of a class_data_item. class Field : public BaseItem { public: - Field(const DexFile& dex_file, - const uint8_t* ptr_pos, - const uint8_t* hiddenapi_ptr_pos = nullptr) - : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos) {} + explicit Field(const DexFile& dex_file, + const uint8_t* ptr_pos) : BaseItem(dex_file, ptr_pos) {} bool IsStatic() const { return is_static_; } + // Unhide the hidden API access flags at the iterator position. TODO: Deprecate. + void UnHideAccessFlags() const; + private: void Read(); @@ -182,9 +185,8 @@ class ClassAccessor { uint32_t position, uint32_t partition_pos, uint32_t iterator_end, - const uint8_t* ptr_pos, - const uint8_t* hiddenapi_ptr_pos) - : data_(dex_file, ptr_pos, hiddenapi_ptr_pos), + const uint8_t* ptr_pos) + : data_(dex_file, ptr_pos), position_(position), partition_pos_(partition_pos), iterator_end_(iterator_end) { @@ -266,16 +268,13 @@ class ClassAccessor { // Not explicit specifically for range-based loops. ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data); - ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, - const DexFile::ClassDef& class_def, - bool parse_hiddenapi_class_data = false); + ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, const DexFile::ClassDef& class_def); ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, uint32_t class_def_index); ClassAccessor(const DexFile& dex_file, const uint8_t* class_data, - uint32_t class_def_index = DexFile::kDexNoIndex32, - bool parse_hiddenapi_class_data = false); + uint32_t class_def_index = DexFile::kDexNoIndex32); // Return the code item for a method. const DexFile::CodeItem* GetCodeItem(const Method& method) const; @@ -354,10 +353,6 @@ class ClassAccessor { return ptr_pos_ != nullptr; } - bool HasHiddenapiClassData() const { - return hiddenapi_ptr_pos_ != nullptr; - } - uint32_t GetClassDefIndex() const { return class_def_index_; } @@ -382,7 +377,6 @@ class ClassAccessor { const DexFile& dex_file_; const uint32_t class_def_index_; const uint8_t* ptr_pos_ = nullptr; // Pointer into stream of class_data_item. - const uint8_t* hiddenapi_ptr_pos_ = nullptr; // Pointer into stream of hiddenapi_metadata. const uint32_t num_static_fields_ = 0u; const uint32_t num_instance_fields_ = 0u; const uint32_t num_direct_methods_ = 0u; diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc index 7ccb9c0bad..48f38ca8a1 100644 --- a/libdexfile/dex/dex_file.cc +++ b/libdexfile/dex/dex_file.cc @@ -46,6 +46,31 @@ static_assert(std::is_trivially_copyable<dex::StringIndex>::value, "StringIndex static_assert(sizeof(dex::TypeIndex) == sizeof(uint16_t), "TypeIndex size is wrong"); static_assert(std::is_trivially_copyable<dex::TypeIndex>::value, "TypeIndex not trivial"); +void DexFile::UnHideAccessFlags(uint8_t* data_ptr, + uint32_t new_access_flags, + bool is_method) { + // Go back 1 uleb to start. + data_ptr = ReverseSearchUnsignedLeb128(data_ptr); + if (is_method) { + // Methods have another uleb field before the access flags + data_ptr = ReverseSearchUnsignedLeb128(data_ptr); + } + DCHECK_EQ(HiddenApiAccessFlags::RemoveFromDex(DecodeUnsignedLeb128WithoutMovingCursor(data_ptr)), + new_access_flags); + UpdateUnsignedLeb128(data_ptr, new_access_flags); +} + +void DexFile::UnhideApis() const { + for (ClassAccessor accessor : GetClasses()) { + for (const ClassAccessor::Field& field : accessor.GetFields()) { + field.UnHideAccessFlags(); + } + for (const ClassAccessor::Method& method : accessor.GetMethods()) { + method.UnHideAccessFlags(); + } + } +} + uint32_t DexFile::CalculateChecksum() const { return CalculateChecksum(Begin(), Size()); } @@ -105,7 +130,6 @@ DexFile::DexFile(const uint8_t* base, num_method_handles_(0), call_site_ids_(nullptr), num_call_site_ids_(0), - hiddenapi_class_data_(nullptr), oat_dex_file_(oat_dex_file), container_(std::move(container)), is_compact_dex_(is_compact_dex), @@ -181,11 +205,6 @@ void DexFile::InitializeSectionsFromMapList() { } else if (map_item.type_ == kDexTypeCallSiteIdItem) { call_site_ids_ = reinterpret_cast<const CallSiteIdItem*>(Begin() + map_item.offset_); num_call_site_ids_ = map_item.size_; - } else if (map_item.type_ == kDexTypeHiddenapiClassData) { - hiddenapi_class_data_ = GetHiddenapiClassDataAtOffset(map_item.offset_); - } else { - // Pointers to other sections are not necessary to retain in the DexFile struct. - // Other items have pointers directly into their data. } } } diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h index 6a52f67646..30d8b6d9bf 100644 --- a/libdexfile/dex/dex_file.h +++ b/libdexfile/dex/dex_file.h @@ -92,7 +92,7 @@ class DexFile { uint32_t endian_tag_ = 0; uint32_t link_size_ = 0; // unused uint32_t link_off_ = 0; // unused - uint32_t map_off_ = 0; // map list offset from data_off_ + uint32_t map_off_ = 0; // unused uint32_t string_ids_size_ = 0; // number of StringIds uint32_t string_ids_off_ = 0; // file offset of StringIds array uint32_t type_ids_size_ = 0; // number of TypeIds, we don't support more than 65535 @@ -134,7 +134,6 @@ class DexFile { kDexTypeAnnotationItem = 0x2004, kDexTypeEncodedArrayItem = 0x2005, kDexTypeAnnotationsDirectoryItem = 0x2006, - kDexTypeHiddenapiClassData = 0xF000, }; struct MapItem { @@ -148,8 +147,6 @@ class DexFile { uint32_t size_; MapItem list_[1]; - size_t Size() const { return sizeof(uint32_t) + (size_ * sizeof(MapItem)); } - private: DISALLOW_COPY_AND_ASSIGN(MapList); }; @@ -422,27 +419,6 @@ class DexFile { DISALLOW_COPY_AND_ASSIGN(AnnotationItem); }; - struct HiddenapiClassData { - uint32_t size_; // total size of the item - uint32_t flags_offset_[1]; // array of offsets from the beginning of this item, - // indexed by class def index - - // Returns a pointer to the beginning of a uleb128-stream of hiddenapi - // flags for a class def of given index. Values are in the same order - // as fields/methods in the class data. Returns null if the class does - // not have class data. - const uint8_t* GetFlagsPointer(uint32_t class_def_idx) const { - if (flags_offset_[class_def_idx] == 0) { - return nullptr; - } else { - return reinterpret_cast<const uint8_t*>(this) + flags_offset_[class_def_idx]; - } - } - - private: - DISALLOW_COPY_AND_ASSIGN(HiddenapiClassData); - }; - enum AnnotationResultStyle { // private kAllObjects, kPrimitivesOrObjects, @@ -861,14 +837,6 @@ class DexFile { return DataPointer<AnnotationItem>(offset); } - ALWAYS_INLINE const HiddenapiClassData* GetHiddenapiClassDataAtOffset(uint32_t offset) const { - return DataPointer<HiddenapiClassData>(offset); - } - - ALWAYS_INLINE const HiddenapiClassData* GetHiddenapiClassData() const { - return hiddenapi_class_data_; - } - const AnnotationItem* GetAnnotationItem(const AnnotationSetItem* set_item, uint32_t index) const { DCHECK_LE(index, set_item->size_); return GetAnnotationItemAtOffset(set_item->entries_[index]); @@ -1024,6 +992,12 @@ class DexFile { return container_.get(); } + // Changes the dex class data pointed to by data_ptr it to not have any hiddenapi flags. + static void UnHideAccessFlags(uint8_t* data_ptr, uint32_t new_access_flags, bool is_method); + + // Iterate dex classes and remove hiddenapi flags in fields and methods. + void UnhideApis() const; + IterationRange<ClassIterator> GetClasses() const; template <typename Visitor> @@ -1106,10 +1080,6 @@ class DexFile { // Number of elements in the call sites list. size_t num_call_site_ids_; - // Points to the base of the hiddenapi class data item_, or nullptr if the dex - // file does not have one. - const HiddenapiClassData* hiddenapi_class_data_; - // If this dex file was loaded from an oat file, oat_dex_file_ contains a // pointer to the OatDexFile it was loaded from. Otherwise oat_dex_file_ is // null. diff --git a/libdexfile/dex/dex_file_verifier.cc b/libdexfile/dex/dex_file_verifier.cc index 43471c3116..499a89b2ab 100644 --- a/libdexfile/dex/dex_file_verifier.cc +++ b/libdexfile/dex/dex_file_verifier.cc @@ -67,7 +67,6 @@ static uint32_t MapTypeToBitMask(DexFile::MapItemType map_item_type) { case DexFile::kDexTypeAnnotationItem: return 1 << 17; case DexFile::kDexTypeEncodedArrayItem: return 1 << 18; case DexFile::kDexTypeAnnotationsDirectoryItem: return 1 << 19; - case DexFile::kDexTypeHiddenapiClassData: return 1 << 20; } return 0; } @@ -95,7 +94,6 @@ static bool IsDataSectionType(DexFile::MapItemType map_item_type) { case DexFile::kDexTypeAnnotationItem: case DexFile::kDexTypeEncodedArrayItem: case DexFile::kDexTypeAnnotationsDirectoryItem: - case DexFile::kDexTypeHiddenapiClassData: return true; } return true; @@ -1098,7 +1096,7 @@ bool DexFileVerifier::CheckIntraClassDataItemFields(size_t count, return false; } if (!CheckClassDataItemField(curr_index, - field->GetAccessFlags(), + field->GetRawAccessFlags(), (*class_def)->access_flags_, *class_type_index, kStatic)) { @@ -1149,7 +1147,7 @@ bool DexFileVerifier::CheckIntraClassDataItemMethods(ClassAccessor::Method* meth return false; } if (!CheckClassDataItemMethod(curr_index, - method->GetAccessFlags(), + method->GetRawAccessFlags(), (*class_def)->access_flags_, *class_type_index, method->GetCodeItemOffset(), @@ -1557,107 +1555,6 @@ bool DexFileVerifier::CheckIntraAnnotationItem() { return true; } -bool DexFileVerifier::CheckIntraHiddenapiClassData() { - const DexFile::HiddenapiClassData* item = - reinterpret_cast<const DexFile::HiddenapiClassData*>(ptr_); - - // Check expected header size. - uint32_t num_header_elems = dex_file_->NumClassDefs() + 1; - uint32_t elem_size = sizeof(uint32_t); - uint32_t header_size = num_header_elems * elem_size; - if (!CheckListSize(item, num_header_elems, elem_size, "hiddenapi class data section header")) { - return false; - } - - // Check total size. - if (!CheckListSize(item, item->size_, 1u, "hiddenapi class data section")) { - return false; - } - - // Check that total size can fit header. - if (item->size_ < header_size) { - ErrorStringPrintf( - "Hiddenapi class data too short to store header (%u < %u)", item->size_, header_size); - return false; - } - - const uint8_t* data_end = ptr_ + item->size_; - ptr_ += header_size; - - // Check offsets for each class def. - for (uint32_t i = 0; i < dex_file_->NumClassDefs(); ++i) { - const DexFile::ClassDef& class_def = dex_file_->GetClassDef(i); - const uint8_t* class_data = dex_file_->GetClassData(class_def); - uint32_t offset = item->flags_offset_[i]; - - if (offset == 0) { - continue; - } - - // Check that class defs with no class data do not have any hiddenapi class data. - if (class_data == nullptr) { - ErrorStringPrintf( - "Hiddenapi class data offset not zero for class def %u with no class data", i); - return false; - } - - // Check that the offset is within the section. - if (offset > item->size_) { - ErrorStringPrintf( - "Hiddenapi class data offset out of section bounds (%u > %u) for class def %u", - offset, item->size_, i); - return false; - } - - // Check that the offset matches current pointer position. We do not allow - // offsets into already parsed data, or gaps between class def data. - uint32_t ptr_offset = ptr_ - reinterpret_cast<const uint8_t*>(item); - if (offset != ptr_offset) { - ErrorStringPrintf( - "Hiddenapi class data unexpected offset (%u != %u) for class def %u", - offset, ptr_offset, i); - return false; - } - - // Parse a uleb128 value for each field and method of this class. - bool failure = false; - auto fn_member = [&](const ClassAccessor::BaseItem& member, const char* member_type) { - if (failure) { - return; - } - uint32_t decoded_flags; - if (!DecodeUnsignedLeb128Checked(&ptr_, data_end, &decoded_flags)) { - ErrorStringPrintf("Hiddenapi class data value out of bounds (%p > %p) for %s %i", - ptr_, data_end, member_type, member.GetIndex()); - failure = true; - return; - } - if (!HiddenApiAccessFlags::AreValidFlags(decoded_flags)) { - ErrorStringPrintf("Hiddenapi class data flags invalid (%u) for %s %i", - decoded_flags, member_type, member.GetIndex()); - failure = true; - return; - } - }; - auto fn_field = [&](const ClassAccessor::Field& field) { fn_member(field, "field"); }; - auto fn_method = [&](const ClassAccessor::Method& method) { fn_member(method, "method"); }; - ClassAccessor accessor(*dex_file_, class_data); - accessor.VisitFieldsAndMethods(fn_field, fn_field, fn_method, fn_method); - if (failure) { - return false; - } - } - - if (ptr_ != data_end) { - ErrorStringPrintf("Hiddenapi class data wrong reported size (%u != %u)", - static_cast<uint32_t>(ptr_ - reinterpret_cast<const uint8_t*>(item)), - item->size_); - return false; - } - - return true; -} - bool DexFileVerifier::CheckIntraAnnotationsDirectoryItem() { const DexFile::AnnotationsDirectoryItem* item = reinterpret_cast<const DexFile::AnnotationsDirectoryItem*>(ptr_); @@ -1872,12 +1769,6 @@ bool DexFileVerifier::CheckIntraSectionIterate(size_t offset, uint32_t section_c } break; } - case DexFile::kDexTypeHiddenapiClassData: { - if (!CheckIntraHiddenapiClassData()) { - return false; - } - break; - } case DexFile::kDexTypeHeaderItem: case DexFile::kDexTypeMapList: break; @@ -2082,7 +1973,6 @@ bool DexFileVerifier::CheckIntraSection() { CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationItem) CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeEncodedArrayItem) CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeAnnotationsDirectoryItem) - CHECK_INTRA_DATA_SECTION_CASE(DexFile::kDexTypeHiddenapiClassData) #undef CHECK_INTRA_DATA_SECTION_CASE } @@ -2846,7 +2736,6 @@ bool DexFileVerifier::CheckInterSectionIterate(size_t offset, case DexFile::kDexTypeDebugInfoItem: case DexFile::kDexTypeAnnotationItem: case DexFile::kDexTypeEncodedArrayItem: - case DexFile::kDexTypeHiddenapiClassData: break; case DexFile::kDexTypeStringIdItem: { if (!CheckInterStringIdItem()) { @@ -2979,8 +2868,7 @@ bool DexFileVerifier::CheckInterSection() { case DexFile::kDexTypeAnnotationSetRefList: case DexFile::kDexTypeAnnotationSetItem: case DexFile::kDexTypeClassDataItem: - case DexFile::kDexTypeAnnotationsDirectoryItem: - case DexFile::kDexTypeHiddenapiClassData: { + case DexFile::kDexTypeAnnotationsDirectoryItem: { if (!CheckInterSectionIterate(section_offset, section_count, type)) { return false; } diff --git a/libdexfile/dex/dex_file_verifier.h b/libdexfile/dex/dex_file_verifier.h index a81df48398..79ddea43d4 100644 --- a/libdexfile/dex/dex_file_verifier.h +++ b/libdexfile/dex/dex_file_verifier.h @@ -126,7 +126,6 @@ class DexFileVerifier { bool CheckIntraDebugInfoItem(); bool CheckIntraAnnotationItem(); bool CheckIntraAnnotationsDirectoryItem(); - bool CheckIntraHiddenapiClassData(); template <DexFile::MapItemType kType> bool CheckIntraSectionIterate(size_t offset, uint32_t count); diff --git a/libdexfile/dex/hidden_api_access_flags.h b/libdexfile/dex/hidden_api_access_flags.h index 837056be80..369615d678 100644 --- a/libdexfile/dex/hidden_api_access_flags.h +++ b/libdexfile/dex/hidden_api_access_flags.h @@ -28,14 +28,31 @@ namespace art { * of information on whether the given class member should be hidden from apps * and under what circumstances. * - * Two bits are encoded for each class member in the HiddenapiClassData item, - * stored in a stream of uleb128-encoded values for each ClassDef item. - * The two bits correspond to values in the ApiList enum below. + * The encoding is different inside DexFile, where we are concerned with size, + * and at runtime where we want to optimize for speed of access. The class + * provides helper functions to decode/encode both of them. * - * At runtime, two bits are set aside in the uint32_t access flags in the - * intrinsics ordinal space (thus intrinsics need to be special-cased). These are - * two consecutive bits and they are directly used to store the integer value of - * the ApiList enum values. + * Encoding in DexFile + * =================== + * + * First bit is encoded as inversion of visibility flags (public/private/protected). + * At most one can be set for any given class member. If two or three are set, + * this is interpreted as the first bit being set and actual visibility flags + * being the complement of the encoded flags. + * + * Second bit is either encoded as bit 5 for fields and non-native methods, where + * it carries no other meaning. If a method is native (bit 8 set), bit 9 is used. + * + * Bits were selected so that they never increase the length of unsigned LEB-128 + * encoding of the access flags. + * + * Encoding at runtime + * =================== + * + * Two bits are set aside in the uint32_t access flags in the intrinsics ordinal + * space (thus intrinsics need to be special-cased). These are two consecutive + * bits and they are directly used to store the integer value of the ApiList + * enum values. * */ class HiddenApiAccessFlags { @@ -48,6 +65,27 @@ class HiddenApiAccessFlags { kNoList, }; + static ALWAYS_INLINE ApiList DecodeFromDex(uint32_t dex_access_flags) { + DexHiddenAccessFlags flags(dex_access_flags); + uint32_t int_value = (flags.IsFirstBitSet() ? 1 : 0) + (flags.IsSecondBitSet() ? 2 : 0); + return static_cast<ApiList>(int_value); + } + + static ALWAYS_INLINE uint32_t RemoveFromDex(uint32_t dex_access_flags) { + DexHiddenAccessFlags flags(dex_access_flags); + flags.SetFirstBit(false); + flags.SetSecondBit(false); + return flags.GetEncoding(); + } + + static ALWAYS_INLINE uint32_t EncodeForDex(uint32_t dex_access_flags, ApiList value) { + DexHiddenAccessFlags flags(RemoveFromDex(dex_access_flags)); + uint32_t int_value = static_cast<uint32_t>(value); + flags.SetFirstBit((int_value & 1) != 0); + flags.SetSecondBit((int_value & 2) != 0); + return flags.GetEncoding(); + } + static ALWAYS_INLINE ApiList DecodeFromRuntime(uint32_t runtime_access_flags) { // This is used in the fast path, only DCHECK here. DCHECK_EQ(runtime_access_flags & kAccIntrinsic, 0u); @@ -65,14 +103,47 @@ class HiddenApiAccessFlags { return runtime_access_flags | hidden_api_flags; } - static ALWAYS_INLINE bool AreValidFlags(uint32_t flags) { - return flags <= static_cast<uint32_t>(kBlacklist); - } - private: static const int kAccFlagsShift = CTZ(kAccHiddenApiBits); static_assert(IsPowerOfTwo((kAccHiddenApiBits >> kAccFlagsShift) + 1), "kAccHiddenApiBits are not continuous"); + + struct DexHiddenAccessFlags { + explicit DexHiddenAccessFlags(uint32_t access_flags) : access_flags_(access_flags) {} + + ALWAYS_INLINE uint32_t GetSecondFlag() { + return ((access_flags_ & kAccNative) != 0) ? kAccDexHiddenBitNative : kAccDexHiddenBit; + } + + ALWAYS_INLINE bool IsFirstBitSet() { + static_assert(IsPowerOfTwo(0u), "Following statement checks if *at most* one bit is set"); + return !IsPowerOfTwo(access_flags_ & kAccVisibilityFlags); + } + + ALWAYS_INLINE void SetFirstBit(bool value) { + if (IsFirstBitSet() != value) { + access_flags_ ^= kAccVisibilityFlags; + } + } + + ALWAYS_INLINE bool IsSecondBitSet() { + return (access_flags_ & GetSecondFlag()) != 0; + } + + ALWAYS_INLINE void SetSecondBit(bool value) { + if (value) { + access_flags_ |= GetSecondFlag(); + } else { + access_flags_ &= ~GetSecondFlag(); + } + } + + ALWAYS_INLINE uint32_t GetEncoding() const { + return access_flags_; + } + + uint32_t access_flags_; + }; }; inline std::ostream& operator<<(std::ostream& os, HiddenApiAccessFlags::ApiList value) { diff --git a/libdexfile/dex/modifiers.h b/libdexfile/dex/modifiers.h index 018b1419b1..38f8455b64 100644 --- a/libdexfile/dex/modifiers.h +++ b/libdexfile/dex/modifiers.h @@ -42,6 +42,11 @@ static constexpr uint32_t kAccEnum = 0x4000; // class, field, ic (1.5) static constexpr uint32_t kAccJavaFlagsMask = 0xffff; // bits set from Java sources (low 16) +// The following flags are used to insert hidden API access flags into boot class path dex files. +// They are decoded by ClassAccessor and removed from the access flags before used by the runtime. +static constexpr uint32_t kAccDexHiddenBit = 0x00000020; // field, method (not native) +static constexpr uint32_t kAccDexHiddenBitNative = 0x00000200; // method (native) + static constexpr uint32_t kAccConstructor = 0x00010000; // method (dex only) <(cl)init> static constexpr uint32_t kAccDeclaredSynchronized = 0x00020000; // method (dex only) static constexpr uint32_t kAccClassIsProxy = 0x00040000; // class (dex only) |
