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