summaryrefslogtreecommitdiffstats
path: root/libdexfile
diff options
context:
space:
mode:
authorDavid Brazdil <dbrazdil@google.com>2018-10-24 12:34:06 +0000
committerDavid Brazdil <dbrazdil@google.com>2018-10-24 12:37:49 +0000
commitd9a0437b0d6cb1438bf21284a2502cbfe293db06 (patch)
tree3bb8a93f499ac537d445e90533598571f3d2d120 /libdexfile
parentfd2aa2bf72563870c9261f248f992a20ac4837a8 (diff)
downloadart-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.h80
-rw-r--r--libdexfile/dex/class_accessor.h60
-rw-r--r--libdexfile/dex/dex_file.cc31
-rw-r--r--libdexfile/dex/dex_file.h44
-rw-r--r--libdexfile/dex/dex_file_verifier.cc118
-rw-r--r--libdexfile/dex/dex_file_verifier.h1
-rw-r--r--libdexfile/dex/hidden_api_access_flags.h93
-rw-r--r--libdexfile/dex/modifiers.h5
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)