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