1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_ 18 #define ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_ 19 20 #include "code_item_accessors.h" 21 #include "dex_file_types.h" 22 #include "invoke_type.h" 23 #include "modifiers.h" 24 25 namespace art { 26 27 namespace dex { 28 struct ClassDef; 29 struct CodeItem; 30 class DexFileVerifier; 31 } // namespace dex 32 33 class ClassIteratorData; 34 class DexFile; 35 template <typename Iter> class IterationRange; 36 class MethodReference; 37 38 // Classes to access Dex data. 39 class ClassAccessor { 40 public: 41 class BaseItem { 42 public: BaseItem(const DexFile & dex_file,const uint8_t * ptr_pos,const uint8_t * hiddenapi_ptr_pos)43 explicit BaseItem(const DexFile& dex_file, 44 const uint8_t* ptr_pos, 45 const uint8_t* hiddenapi_ptr_pos) 46 : dex_file_(dex_file), ptr_pos_(ptr_pos), hiddenapi_ptr_pos_(hiddenapi_ptr_pos) {} 47 GetIndex()48 uint32_t GetIndex() const { 49 return index_; 50 } 51 GetAccessFlags()52 uint32_t GetAccessFlags() const { 53 return access_flags_; 54 } 55 GetHiddenapiFlags()56 uint32_t GetHiddenapiFlags() const { 57 return hiddenapi_flags_; 58 } 59 IsFinal()60 bool IsFinal() const { 61 return (GetAccessFlags() & kAccFinal) != 0; 62 } 63 GetDexFile()64 const DexFile& GetDexFile() const { 65 return dex_file_; 66 } 67 GetDataPointer()68 const uint8_t* GetDataPointer() const { 69 return ptr_pos_; 70 } 71 MemberIsNative()72 bool MemberIsNative() const { 73 return GetAccessFlags() & kAccNative; 74 } 75 MemberIsFinal()76 bool MemberIsFinal() const { 77 return GetAccessFlags() & kAccFinal; 78 } 79 80 protected: 81 // Internal data pointer for reading. 82 const DexFile& dex_file_; 83 const uint8_t* ptr_pos_ = nullptr; 84 const uint8_t* hiddenapi_ptr_pos_ = nullptr; 85 uint32_t index_ = 0u; 86 uint32_t access_flags_ = 0u; 87 uint32_t hiddenapi_flags_ = 0u; 88 }; 89 90 // A decoded version of the method of a class_data_item. 91 class Method : public BaseItem { 92 public: GetCodeItemOffset()93 uint32_t GetCodeItemOffset() const { 94 return code_off_; 95 } 96 GetInvokeType(uint32_t class_access_flags)97 InvokeType GetInvokeType(uint32_t class_access_flags) const { 98 return is_static_or_direct_ 99 ? GetDirectMethodInvokeType() 100 : GetVirtualMethodInvokeType(class_access_flags); 101 } 102 103 MethodReference GetReference() const; 104 105 CodeItemInstructionAccessor GetInstructions() const; 106 CodeItemDataAccessor GetInstructionsAndData() const; 107 108 const dex::CodeItem* GetCodeItem() const; 109 IsStaticOrDirect()110 bool IsStaticOrDirect() const { 111 return is_static_or_direct_; 112 } 113 114 private: 115 Method(const DexFile& dex_file, 116 const uint8_t* ptr_pos, 117 const uint8_t* hiddenapi_ptr_pos = nullptr, 118 bool is_static_or_direct = true) BaseItem(dex_file,ptr_pos,hiddenapi_ptr_pos)119 : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos), 120 is_static_or_direct_(is_static_or_direct) {} 121 122 void Read(); 123 GetDirectMethodInvokeType()124 InvokeType GetDirectMethodInvokeType() const { 125 return (GetAccessFlags() & kAccStatic) != 0 ? kStatic : kDirect; 126 } 127 GetVirtualMethodInvokeType(uint32_t class_access_flags)128 InvokeType GetVirtualMethodInvokeType(uint32_t class_access_flags) const { 129 DCHECK_EQ(GetAccessFlags() & kAccStatic, 0U); 130 if ((class_access_flags & kAccInterface) != 0) { 131 return kInterface; 132 } else if ((GetAccessFlags() & kAccConstructor) != 0) { 133 return kSuper; 134 } else { 135 return kVirtual; 136 } 137 } 138 139 // Move to virtual method section. NextSection()140 void NextSection() { 141 DCHECK(is_static_or_direct_) << "Already in the virtual methods section"; 142 is_static_or_direct_ = false; 143 index_ = 0u; 144 } 145 146 bool is_static_or_direct_ = true; 147 uint32_t code_off_ = 0u; 148 149 friend class ClassAccessor; 150 friend class dex::DexFileVerifier; 151 }; 152 153 // A decoded version of the field of a class_data_item. 154 class Field : public BaseItem { 155 public: 156 Field(const DexFile& dex_file, 157 const uint8_t* ptr_pos, 158 const uint8_t* hiddenapi_ptr_pos = nullptr) BaseItem(dex_file,ptr_pos,hiddenapi_ptr_pos)159 : BaseItem(dex_file, ptr_pos, hiddenapi_ptr_pos) {} 160 IsStatic()161 bool IsStatic() const { 162 return is_static_; 163 } 164 165 private: 166 void Read(); 167 168 // Move to instance fields section. NextSection()169 void NextSection() { 170 index_ = 0u; 171 is_static_ = false; 172 } 173 174 bool is_static_ = true; 175 friend class ClassAccessor; 176 friend class dex::DexFileVerifier; 177 }; 178 179 template <typename DataType> 180 class DataIterator : public std::iterator<std::forward_iterator_tag, DataType> { 181 public: 182 using value_type = typename std::iterator<std::forward_iterator_tag, DataType>::value_type; 183 using difference_type = 184 typename std::iterator<std::forward_iterator_tag, value_type>::difference_type; 185 DataIterator(const DexFile & dex_file,uint32_t position,uint32_t partition_pos,uint32_t iterator_end,const uint8_t * ptr_pos,const uint8_t * hiddenapi_ptr_pos)186 DataIterator(const DexFile& dex_file, 187 uint32_t position, 188 uint32_t partition_pos, 189 uint32_t iterator_end, 190 const uint8_t* ptr_pos, 191 const uint8_t* hiddenapi_ptr_pos) 192 : data_(dex_file, ptr_pos, hiddenapi_ptr_pos), 193 position_(position), 194 partition_pos_(partition_pos), 195 iterator_end_(iterator_end) { 196 ReadData(); 197 } 198 IsValid()199 bool IsValid() const { 200 return position_ < iterator_end_; 201 } 202 203 // Value after modification. 204 DataIterator& operator++() { 205 ++position_; 206 ReadData(); 207 return *this; 208 } 209 210 const value_type& operator*() const { 211 return data_; 212 } 213 214 const value_type* operator->() const { 215 return &data_; 216 } 217 218 bool operator==(const DataIterator& rhs) const { 219 DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files."; 220 return position_ == rhs.position_; 221 } 222 223 bool operator!=(const DataIterator& rhs) const { 224 return !(*this == rhs); 225 } 226 227 bool operator<(const DataIterator& rhs) const { 228 DCHECK_EQ(&data_.dex_file_, &rhs.data_.dex_file_) << "Comparing different dex files."; 229 return position_ < rhs.position_; 230 } 231 232 bool operator>(const DataIterator& rhs) const { 233 return rhs < *this; 234 } 235 236 bool operator<=(const DataIterator& rhs) const { 237 return !(rhs < *this); 238 } 239 240 bool operator>=(const DataIterator& rhs) const { 241 return !(*this < rhs); 242 } 243 GetDataPointer()244 const uint8_t* GetDataPointer() const { 245 return data_.ptr_pos_; 246 } 247 248 private: 249 // Read data at current position. ReadData()250 void ReadData() { 251 if (IsValid()) { 252 // At the end of the first section, go to the next section. 253 if (position_ == partition_pos_) { 254 data_.NextSection(); 255 } 256 data_.Read(); 257 } 258 } 259 260 DataType data_; 261 // Iterator position. 262 uint32_t position_; 263 // At partition_pos_, we go to the next section. 264 const uint32_t partition_pos_; 265 // At iterator_end_, the iterator is no longer valid. 266 const uint32_t iterator_end_; 267 268 friend class dex::DexFileVerifier; 269 }; 270 271 // Not explicit specifically for range-based loops. 272 ALWAYS_INLINE ClassAccessor(const ClassIteratorData& data); // NOLINT [runtime/explicit] [5] 273 274 ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, 275 const dex::ClassDef& class_def, 276 bool parse_hiddenapi_class_data = false); 277 278 ALWAYS_INLINE ClassAccessor(const DexFile& dex_file, uint32_t class_def_index); 279 280 ClassAccessor(const DexFile& dex_file, 281 const uint8_t* class_data, 282 uint32_t class_def_index = dex::kDexNoIndex, 283 bool parse_hiddenapi_class_data = false); 284 285 // Return the code item for a method. 286 const dex::CodeItem* GetCodeItem(const Method& method) const; 287 288 // Iterator data is not very iterator friendly, use visitors to get around this. 289 template <typename StaticFieldVisitor, 290 typename InstanceFieldVisitor, 291 typename DirectMethodVisitor, 292 typename VirtualMethodVisitor> 293 void VisitFieldsAndMethods(const StaticFieldVisitor& static_field_visitor, 294 const InstanceFieldVisitor& instance_field_visitor, 295 const DirectMethodVisitor& direct_method_visitor, 296 const VirtualMethodVisitor& virtual_method_visitor) const; 297 298 template <typename DirectMethodVisitor, 299 typename VirtualMethodVisitor> 300 void VisitMethods(const DirectMethodVisitor& direct_method_visitor, 301 const VirtualMethodVisitor& virtual_method_visitor) const; 302 303 template <typename StaticFieldVisitor, 304 typename InstanceFieldVisitor> 305 void VisitFields(const StaticFieldVisitor& static_field_visitor, 306 const InstanceFieldVisitor& instance_field_visitor) const; 307 308 // Return the iteration range for all the fields. 309 IterationRange<DataIterator<Field>> GetFields() const; 310 311 // Return the iteration range for all the static fields. 312 IterationRange<DataIterator<Field>> GetStaticFields() const; 313 314 // Return the iteration range for all the instance fields. 315 IterationRange<DataIterator<Field>> GetInstanceFields() const; 316 317 // Return the iteration range for all the methods. 318 IterationRange<DataIterator<Method>> GetMethods() const; 319 320 // Return the iteration range for the direct methods. 321 IterationRange<DataIterator<Method>> GetDirectMethods() const; 322 323 // Return the iteration range for the virtual methods. 324 IterationRange<DataIterator<Method>> GetVirtualMethods() const; 325 NumStaticFields()326 uint32_t NumStaticFields() const { 327 return num_static_fields_; 328 } 329 NumInstanceFields()330 uint32_t NumInstanceFields() const { 331 return num_instance_fields_; 332 } 333 NumFields()334 uint32_t NumFields() const { 335 return NumStaticFields() + NumInstanceFields(); 336 } 337 NumDirectMethods()338 uint32_t NumDirectMethods() const { 339 return num_direct_methods_; 340 } 341 NumVirtualMethods()342 uint32_t NumVirtualMethods() const { 343 return num_virtual_methods_; 344 } 345 NumMethods()346 uint32_t NumMethods() const { 347 return NumDirectMethods() + NumVirtualMethods(); 348 } 349 350 const char* GetDescriptor() const; 351 352 dex::TypeIndex GetClassIdx() const; 353 GetDexFile()354 const DexFile& GetDexFile() const { 355 return dex_file_; 356 } 357 HasClassData()358 bool HasClassData() const { 359 return ptr_pos_ != nullptr; 360 } 361 HasHiddenapiClassData()362 bool HasHiddenapiClassData() const { 363 return hiddenapi_ptr_pos_ != nullptr; 364 } 365 GetClassDefIndex()366 uint32_t GetClassDefIndex() const { 367 return class_def_index_; 368 } 369 370 const dex::ClassDef& GetClassDef() const; 371 372 protected: 373 // Template visitor to reduce copy paste for visiting elements. 374 // No thread safety analysis since the visitor may require capabilities. 375 template <typename DataType, typename Visitor> 376 void VisitMembers(size_t count, const Visitor& visitor, DataType* data) const 377 NO_THREAD_SAFETY_ANALYSIS; 378 379 // Return an iteration range for the first <count> fields. 380 IterationRange<DataIterator<Field>> GetFieldsInternal(size_t count) const; 381 382 // Return an iteration range for the first <count> methods. 383 IterationRange<DataIterator<Method>> GetMethodsInternal(size_t count) const; 384 385 const DexFile& dex_file_; 386 const uint32_t class_def_index_; 387 const uint8_t* ptr_pos_ = nullptr; // Pointer into stream of class_data_item. 388 const uint8_t* hiddenapi_ptr_pos_ = nullptr; // Pointer into stream of hiddenapi_metadata. 389 const uint32_t num_static_fields_ = 0u; 390 const uint32_t num_instance_fields_ = 0u; 391 const uint32_t num_direct_methods_ = 0u; 392 const uint32_t num_virtual_methods_ = 0u; 393 394 friend class dex::DexFileVerifier; 395 }; 396 397 } // namespace art 398 399 #endif // ART_LIBDEXFILE_DEX_CLASS_ACCESSOR_H_ 400