diff options
Diffstat (limited to 'runtime/dex_file.h')
| -rw-r--r-- | runtime/dex_file.h | 643 |
1 files changed, 306 insertions, 337 deletions
diff --git a/runtime/dex_file.h b/runtime/dex_file.h index 638821bfb7..591ba42003 100644 --- a/runtime/dex_file.h +++ b/runtime/dex_file.h @@ -19,42 +19,25 @@ #include <memory> #include <string> -#include <unordered_map> #include <vector> #include "base/logging.h" -#include "base/mutex.h" // For Locks::mutator_lock_. #include "base/value_object.h" +#include "dex_file_types.h" #include "globals.h" #include "invoke_type.h" #include "jni.h" -#include "jvalue.h" -#include "mirror/object_array.h" #include "modifiers.h" #include "utf.h" namespace art { -// TODO: remove dependencies on mirror classes, primarily by moving -// EncodedStaticFieldValueIterator to its own file. -namespace mirror { - class ClassLoader; - class DexCache; -} // namespace mirror -class ArtField; -class ArtMethod; -class ClassLinker; -template <class Key, class Value, class EmptyFn, class HashFn, class Pred, class Alloc> -class HashMap; class MemMap; class OatDexFile; class Signature; -template<class T> class Handle; class StringPiece; -class TypeLookupTable; class ZipArchive; -// TODO: move all of the macro functionality into the DexCache class. class DexFile { public: // First Dex format version supporting default methods. @@ -63,7 +46,7 @@ class DexFile { static const uint32_t kClassDefinitionOrderEnforcedVersion = 37; static const uint8_t kDexMagic[]; - static constexpr size_t kNumDexVersions = 2; + static constexpr size_t kNumDexVersions = 3; static constexpr size_t kDexVersionLen = 4; static const uint8_t kDexMagicVersions[kNumDexVersions][kDexVersionLen]; @@ -109,8 +92,8 @@ class DexFile { uint32_t method_ids_off_; // file offset of MethodIds array uint32_t class_defs_size_; // number of ClassDefs uint32_t class_defs_off_; // file offset of ClassDef array - uint32_t data_size_; // unused - uint32_t data_off_; // unused + uint32_t data_size_; // size of data section + uint32_t data_off_; // file offset of data section // Decode the dex magic version uint32_t GetVersion() const; @@ -120,7 +103,7 @@ class DexFile { }; // Map item type codes. - enum { + enum MapItemType : uint16_t { // private kDexTypeHeaderItem = 0x0000, kDexTypeStringIdItem = 0x0001, kDexTypeTypeIdItem = 0x0002, @@ -128,6 +111,8 @@ class DexFile { kDexTypeFieldIdItem = 0x0004, kDexTypeMethodIdItem = 0x0005, kDexTypeClassDefItem = 0x0006, + kDexTypeCallSiteIdItem = 0x0007, + kDexTypeMethodHandleItem = 0x0008, kDexTypeMapList = 0x1000, kDexTypeTypeList = 0x1001, kDexTypeAnnotationSetRefList = 0x1002, @@ -169,7 +154,7 @@ class DexFile { // Raw type_id_item. struct TypeId { - uint32_t descriptor_idx_; // index into string_ids + dex::StringIndex descriptor_idx_; // index into string_ids private: DISALLOW_COPY_AND_ASSIGN(TypeId); @@ -177,44 +162,44 @@ class DexFile { // Raw field_id_item. struct FieldId { - uint16_t class_idx_; // index into type_ids_ array for defining class - uint16_t type_idx_; // index into type_ids_ array for field type - uint32_t name_idx_; // index into string_ids_ array for field name + dex::TypeIndex class_idx_; // index into type_ids_ array for defining class + dex::TypeIndex type_idx_; // index into type_ids_ array for field type + dex::StringIndex name_idx_; // index into string_ids_ array for field name private: DISALLOW_COPY_AND_ASSIGN(FieldId); }; - // Raw method_id_item. - struct MethodId { - uint16_t class_idx_; // index into type_ids_ array for defining class - uint16_t proto_idx_; // index into proto_ids_ array for method prototype - uint32_t name_idx_; // index into string_ids_ array for method name + // Raw proto_id_item. + struct ProtoId { + dex::StringIndex shorty_idx_; // index into string_ids array for shorty descriptor + dex::TypeIndex return_type_idx_; // index into type_ids array for return type + uint16_t pad_; // padding = 0 + uint32_t parameters_off_; // file offset to type_list for parameter types private: - DISALLOW_COPY_AND_ASSIGN(MethodId); + DISALLOW_COPY_AND_ASSIGN(ProtoId); }; - // Raw proto_id_item. - struct ProtoId { - uint32_t shorty_idx_; // index into string_ids array for shorty descriptor - uint16_t return_type_idx_; // index into type_ids array for return type - uint16_t pad_; // padding = 0 - uint32_t parameters_off_; // file offset to type_list for parameter types + // Raw method_id_item. + struct MethodId { + dex::TypeIndex class_idx_; // index into type_ids_ array for defining class + uint16_t proto_idx_; // index into proto_ids_ array for method prototype + dex::StringIndex name_idx_; // index into string_ids_ array for method name private: - DISALLOW_COPY_AND_ASSIGN(ProtoId); + DISALLOW_COPY_AND_ASSIGN(MethodId); }; // Raw class_def_item. struct ClassDef { - uint16_t class_idx_; // index into type_ids_ array for this class + dex::TypeIndex class_idx_; // index into type_ids_ array for this class uint16_t pad1_; // padding = 0 uint32_t access_flags_; - uint16_t superclass_idx_; // index into type_ids_ array for superclass + dex::TypeIndex superclass_idx_; // index into type_ids_ array for superclass uint16_t pad2_; // padding = 0 uint32_t interfaces_off_; // file offset to TypeList - uint32_t source_file_idx_; // index into string_ids_ for source file name + dex::StringIndex source_file_idx_; // index into string_ids_ for source file name uint32_t annotations_off_; // file offset to annotations_directory_item uint32_t class_data_off_; // file offset to class_data_item uint32_t static_values_off_; // file offset to EncodedArray @@ -243,7 +228,7 @@ class DexFile { // Raw type_item. struct TypeItem { - uint16_t type_idx_; // index into type_ids section + dex::TypeIndex type_idx_; // index into type_ids section private: DISALLOW_COPY_AND_ASSIGN(TypeItem); @@ -277,6 +262,37 @@ class DexFile { DISALLOW_COPY_AND_ASSIGN(TypeList); }; + // MethodHandle Types + enum class MethodHandleType : uint16_t { // private + kStaticPut = 0x0000, // a setter for a given static field. + kStaticGet = 0x0001, // a getter for a given static field. + kInstancePut = 0x0002, // a setter for a given instance field. + kInstanceGet = 0x0003, // a getter for a given instance field. + kInvokeStatic = 0x0004, // an invoker for a given static method. + kInvokeInstance = 0x0005, // invoke_instance : an invoker for a given instance method. This + // can be any non-static method on any class (or interface) except + // for “<init>”. + kInvokeConstructor = 0x0006, // an invoker for a given constructor. + kLast = kInvokeConstructor + }; + + // raw method_handle_item + struct MethodHandleItem { + uint16_t method_handle_type_; + uint16_t reserved1_; // Reserved for future use. + uint16_t field_or_method_idx_; // Field index for accessors, method index otherwise. + uint16_t reserved2_; // Reserved for future use. + private: + DISALLOW_COPY_AND_ASSIGN(MethodHandleItem); + }; + + // raw call_site_id_item + struct CallSiteIdItem { + uint32_t data_off_; // Offset into data section pointing to encoded array items. + private: + DISALLOW_COPY_AND_ASSIGN(CallSiteIdItem); + }; + // Raw code_item. struct CodeItem { uint16_t registers_size_; // the number of registers used by this code @@ -319,6 +335,8 @@ class DexFile { kDexAnnotationLong = 0x06, kDexAnnotationFloat = 0x10, kDexAnnotationDouble = 0x11, + kDexAnnotationMethodType = 0x15, + kDexAnnotationMethodHandle = 0x16, kDexAnnotationString = 0x17, kDexAnnotationType = 0x18, kDexAnnotationField = 0x19, @@ -398,43 +416,64 @@ class DexFile { DISALLOW_COPY_AND_ASSIGN(AnnotationItem); }; - struct AnnotationValue { - JValue value_; - uint8_t type_; - }; - enum AnnotationResultStyle { // private kAllObjects, kPrimitivesOrObjects, kAllRaw }; - // Returns the checksum of a file for comparison with GetLocationChecksum(). - // For .dex files, this is the header checksum. - // For zip files, this is the classes.dex zip entry CRC32 checksum. - // Return true if the checksum could be found, false otherwise. - static bool GetChecksum(const char* filename, uint32_t* checksum, std::string* error_msg); + struct AnnotationValue; - // Opens .dex files found in the container, guessing the container format based on file extension. - static bool Open(const char* filename, const char* location, std::string* error_msg, - std::vector<std::unique_ptr<const DexFile>>* dex_files); + // Returns the checksums of a file for comparison with GetLocationChecksum(). + // For .dex files, this is the single header checksum. + // For zip files, this is the zip entry CRC32 checksum for classes.dex and + // each additional multidex entry classes2.dex, classes3.dex, etc. + // Return true if the checksums could be found, false otherwise. + static bool GetMultiDexChecksums(const char* filename, + std::vector<uint32_t>* checksums, + std::string* error_msg); - // Checks whether the given file has the dex magic, or is a zip file with a classes.dex entry. - // If this function returns false, Open will not succeed. The inverse is not true, however. - static bool MaybeDex(const char* filename); + // Check whether a location denotes a multidex dex file. This is a very simple check: returns + // whether the string contains the separator character. + static bool IsMultiDexLocation(const char* location); // Opens .dex file, backed by existing memory - static std::unique_ptr<const DexFile> Open(const uint8_t* base, size_t size, + static std::unique_ptr<const DexFile> Open(const uint8_t* base, + size_t size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, + bool verify_checksum, std::string* error_msg); - // Open all classesXXX.dex files from a zip archive. - static bool OpenFromZip(const ZipArchive& zip_archive, const std::string& location, - std::string* error_msg, - std::vector<std::unique_ptr<const DexFile>>* dex_files); + // Opens .dex file that has been memory-mapped by the caller. + static std::unique_ptr<const DexFile> Open(const std::string& location, + uint32_t location_checkum, + std::unique_ptr<MemMap> mem_map, + bool verify, + bool verify_checksum, + std::string* error_msg); + + // Opens all .dex files found in the file, guessing the container format based on file extension. + static bool Open(const char* filename, + const std::string& location, + bool verify_checksum, + std::string* error_msg, + std::vector<std::unique_ptr<const DexFile>>* dex_files); + + // Open a single dex file from an fd. + static std::unique_ptr<const DexFile> OpenDex(int fd, + const std::string& location, + bool verify_checksum, + std::string* error_msg); + + // Opens dex files from within a .jar, .zip, or .apk file + static bool OpenZip(int fd, + const std::string& location, + bool verify_checksum, + std::string* error_msg, + std::vector<std::unique_ptr<const DexFile>>* dex_files); // Closes a .dex file. virtual ~DexFile(); @@ -504,15 +543,15 @@ class DexFile { } // Returns the StringId at the specified index. - const StringId& GetStringId(uint32_t idx) const { - DCHECK_LT(idx, NumStringIds()) << GetLocation(); - return string_ids_[idx]; + const StringId& GetStringId(dex::StringIndex idx) const { + DCHECK_LT(idx.index_, NumStringIds()) << GetLocation(); + return string_ids_[idx.index_]; } - uint32_t GetIndexForStringId(const StringId& string_id) const { + dex::StringIndex GetIndexForStringId(const StringId& string_id) const { CHECK_GE(&string_id, string_ids_) << GetLocation(); CHECK_LT(&string_id, string_ids_ + header_->string_ids_size_) << GetLocation(); - return &string_id - string_ids_; + return dex::StringIndex(&string_id - string_ids_); } int32_t GetStringLength(const StringId& string_id) const; @@ -522,25 +561,12 @@ class DexFile { // as the string length of the string data. const char* GetStringDataAndUtf16Length(const StringId& string_id, uint32_t* utf16_length) const; - const char* GetStringData(const StringId& string_id) const { - uint32_t ignored; - return GetStringDataAndUtf16Length(string_id, &ignored); - } + const char* GetStringData(const StringId& string_id) const; // Index version of GetStringDataAndUtf16Length. - const char* StringDataAndUtf16LengthByIdx(uint32_t idx, uint32_t* utf16_length) const { - if (idx == kDexNoIndex) { - *utf16_length = 0; - return nullptr; - } - const StringId& string_id = GetStringId(idx); - return GetStringDataAndUtf16Length(string_id, utf16_length); - } + const char* StringDataAndUtf16LengthByIdx(dex::StringIndex idx, uint32_t* utf16_length) const; - const char* StringDataByIdx(uint32_t idx) const { - uint32_t unicode_length; - return StringDataAndUtf16LengthByIdx(idx, &unicode_length); - } + const char* StringDataByIdx(dex::StringIndex idx) const; // Looks up a string id for a given modified utf8 string. const StringId* FindStringId(const char* string) const; @@ -556,38 +582,34 @@ class DexFile { return header_->type_ids_size_; } + bool IsTypeIndexValid(dex::TypeIndex idx) const { + return idx.IsValid() && idx.index_ < NumTypeIds(); + } + // Returns the TypeId at the specified index. - const TypeId& GetTypeId(uint32_t idx) const { - DCHECK_LT(idx, NumTypeIds()) << GetLocation(); - return type_ids_[idx]; + const TypeId& GetTypeId(dex::TypeIndex idx) const { + DCHECK_LT(idx.index_, NumTypeIds()) << GetLocation(); + return type_ids_[idx.index_]; } - uint16_t GetIndexForTypeId(const TypeId& type_id) const { + dex::TypeIndex GetIndexForTypeId(const TypeId& type_id) const { CHECK_GE(&type_id, type_ids_) << GetLocation(); CHECK_LT(&type_id, type_ids_ + header_->type_ids_size_) << GetLocation(); size_t result = &type_id - type_ids_; DCHECK_LT(result, 65536U) << GetLocation(); - return static_cast<uint16_t>(result); + return dex::TypeIndex(static_cast<uint16_t>(result)); } // Get the descriptor string associated with a given type index. - const char* StringByTypeIdx(uint32_t idx, uint32_t* unicode_length) const { - const TypeId& type_id = GetTypeId(idx); - return StringDataAndUtf16LengthByIdx(type_id.descriptor_idx_, unicode_length); - } + const char* StringByTypeIdx(dex::TypeIndex idx, uint32_t* unicode_length) const; - const char* StringByTypeIdx(uint32_t idx) const { - const TypeId& type_id = GetTypeId(idx); - return StringDataByIdx(type_id.descriptor_idx_); - } + const char* StringByTypeIdx(dex::TypeIndex idx) const; // Returns the type descriptor string of a type id. - const char* GetTypeDescriptor(const TypeId& type_id) const { - return StringDataByIdx(type_id.descriptor_idx_); - } + const char* GetTypeDescriptor(const TypeId& type_id) const; // Looks up a type for the given string index - const TypeId* FindTypeId(uint32_t string_idx) const; + const TypeId* FindTypeId(dex::StringIndex string_idx) const; // Returns the number of field identifiers in the .dex file. size_t NumFieldIds() const { @@ -612,6 +634,9 @@ class DexFile { const DexFile::StringId& name, const DexFile::TypeId& type) const; + uint32_t FindCodeItemOffset(const DexFile::ClassDef& class_def, + uint32_t dex_method_idx) const; + // Returns the declaring class descriptor string of a field id. const char* GetFieldDeclaringClassDescriptor(const FieldId& field_id) const { const DexFile::TypeId& type_id = GetTypeId(field_id.class_idx_); @@ -619,15 +644,10 @@ class DexFile { } // Returns the class descriptor string of a field id. - const char* GetFieldTypeDescriptor(const FieldId& field_id) const { - const DexFile::TypeId& type_id = GetTypeId(field_id.type_idx_); - return GetTypeDescriptor(type_id); - } + const char* GetFieldTypeDescriptor(const FieldId& field_id) const; // Returns the name of a field id. - const char* GetFieldName(const FieldId& field_id) const { - return StringDataByIdx(field_id.name_idx_); - } + const char* GetFieldName(const FieldId& field_id) const; // Returns the number of method identifiers in the .dex file. size_t NumMethodIds() const { @@ -653,10 +673,7 @@ class DexFile { const DexFile::ProtoId& signature) const; // Returns the declaring class descriptor string of a method id. - const char* GetMethodDeclaringClassDescriptor(const MethodId& method_id) const { - const DexFile::TypeId& type_id = GetTypeId(method_id.class_idx_); - return GetTypeDescriptor(type_id); - } + const char* GetMethodDeclaringClassDescriptor(const MethodId& method_id) const; // Returns the prototype of a method id. const ProtoId& GetMethodPrototype(const MethodId& method_id) const { @@ -666,24 +683,19 @@ class DexFile { // Returns a representation of the signature of a method id. const Signature GetMethodSignature(const MethodId& method_id) const; + // Returns a representation of the signature of a proto id. + const Signature GetProtoSignature(const ProtoId& proto_id) const; + // Returns the name of a method id. - const char* GetMethodName(const MethodId& method_id) const { - return StringDataByIdx(method_id.name_idx_); - } + const char* GetMethodName(const MethodId& method_id) const; // Returns the shorty of a method by its index. - const char* GetMethodShorty(uint32_t idx) const { - return StringDataByIdx(GetProtoId(GetMethodId(idx).proto_idx_).shorty_idx_); - } + const char* GetMethodShorty(uint32_t idx) const; // Returns the shorty of a method id. - const char* GetMethodShorty(const MethodId& method_id) const { - return StringDataByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_); - } - const char* GetMethodShorty(const MethodId& method_id, uint32_t* length) const { - // Using the UTF16 length is safe here as shorties are guaranteed to be ASCII characters. - return StringDataAndUtf16LengthByIdx(GetProtoId(method_id.proto_idx_).shorty_idx_, length); - } + const char* GetMethodShorty(const MethodId& method_id) const; + const char* GetMethodShorty(const MethodId& method_id, uint32_t* length) const; + // Returns the number of class definitions in the .dex file. uint32_t NumClassDefs() const { DCHECK(header_ != nullptr) << GetLocation(); @@ -703,16 +715,10 @@ class DexFile { } // Returns the class descriptor string of a class definition. - const char* GetClassDescriptor(const ClassDef& class_def) const { - return StringByTypeIdx(class_def.class_idx_); - } - - // Looks up a class definition by its class descriptor. Hash must be - // ComputeModifiedUtf8Hash(descriptor). - const ClassDef* FindClassDef(const char* descriptor, size_t hash) const; + const char* GetClassDescriptor(const ClassDef& class_def) const; // Looks up a class definition by its type index. - const ClassDef* FindClassDef(uint16_t type_idx) const; + const ClassDef* FindClassDef(dex::TypeIndex type_idx) const; const TypeList* GetInterfacesList(const ClassDef& class_def) const { if (class_def.interfaces_off_ == 0) { @@ -723,6 +729,24 @@ class DexFile { } } + uint32_t NumMethodHandles() const { + return num_method_handles_; + } + + const MethodHandleItem& GetMethodHandle(uint32_t idx) const { + CHECK_LT(idx, NumMethodHandles()); + return method_handles_[idx]; + } + + uint32_t NumCallSiteIds() const { + return num_call_site_ids_; + } + + const CallSiteIdItem& GetCallSiteId(uint32_t idx) const { + CHECK_LT(idx, NumCallSiteIds()); + return call_site_ids_[idx]; + } + // Returns a pointer to the raw memory mapped class_data_item const uint8_t* GetClassData(const ClassDef& class_def) const { if (class_def.class_data_off_ == 0) { @@ -743,9 +767,7 @@ class DexFile { } } - const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const { - return StringByTypeIdx(proto_id.return_type_idx_); - } + const char* GetReturnTypeDescriptor(const ProtoId& proto_id) const; // Returns the number of prototype identifiers in the .dex file. size_t NumProtoIds() const { @@ -754,7 +776,7 @@ class DexFile { } // Returns the ProtoId at the specified index. - const ProtoId& GetProtoId(uint32_t idx) const { + const ProtoId& GetProtoId(uint16_t idx) const { DCHECK_LT(idx, NumProtoIds()) << GetLocation(); return proto_ids_[idx]; } @@ -766,26 +788,25 @@ class DexFile { } // Looks up a proto id for a given return type and signature type list - const ProtoId* FindProtoId(uint16_t return_type_idx, - const uint16_t* signature_type_idxs, uint32_t signature_length) const; - const ProtoId* FindProtoId(uint16_t return_type_idx, - const std::vector<uint16_t>& signature_type_idxs) const { + const ProtoId* FindProtoId(dex::TypeIndex return_type_idx, + const dex::TypeIndex* signature_type_idxs, + uint32_t signature_length) const; + const ProtoId* FindProtoId(dex::TypeIndex return_type_idx, + const std::vector<dex::TypeIndex>& signature_type_idxs) const { return FindProtoId(return_type_idx, &signature_type_idxs[0], signature_type_idxs.size()); } // Given a signature place the type ids into the given vector, returns true on success - bool CreateTypeList(const StringPiece& signature, uint16_t* return_type_idx, - std::vector<uint16_t>* param_type_idxs) const; + bool CreateTypeList(const StringPiece& signature, + dex::TypeIndex* return_type_idx, + std::vector<dex::TypeIndex>* param_type_idxs) const; // Create a Signature from the given string signature or return Signature::NoSignature if not // possible. const Signature CreateSignature(const StringPiece& signature) const; // Returns the short form method descriptor for the given prototype. - const char* GetShorty(uint32_t proto_idx) const { - const ProtoId& proto_id = GetProtoId(proto_idx); - return StringDataByIdx(proto_id.shorty_idx_); - } + const char* GetShorty(uint32_t proto_idx) const; const TypeList* GetProtoParameters(const ProtoId& proto_id) const { if (proto_id.parameters_off_ == 0) { @@ -804,6 +825,10 @@ class DexFile { } } + const uint8_t* GetCallSiteEncodedValuesArray(const CallSiteIdItem& call_site_id) const { + return begin_ + call_site_id.data_off_; + } + static const TryItem* GetTryItems(const CodeItem& code_item, uint32_t offset); // Get the base of the encoded data for the given DexCode. @@ -971,108 +996,6 @@ class DexFile { return reinterpret_cast<const AnnotationSetItem*>(begin_ + offset); } - const AnnotationSetItem* FindAnnotationSetForField(ArtField* field) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Object* GetAnnotationForField(ArtField* field, Handle<mirror::Class> annotation_class) - const SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::Object>* GetAnnotationsForField(ArtField* field) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForField(ArtField* field) const - SHARED_REQUIRES(Locks::mutator_lock_); - bool IsFieldAnnotationPresent(ArtField* field, Handle<mirror::Class> annotation_class) const - SHARED_REQUIRES(Locks::mutator_lock_); - - const AnnotationSetItem* FindAnnotationSetForMethod(ArtMethod* method) const - SHARED_REQUIRES(Locks::mutator_lock_); - const ParameterAnnotationsItem* FindAnnotationsItemForMethod(ArtMethod* method) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Object* GetAnnotationDefaultValue(ArtMethod* method) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Object* GetAnnotationForMethod(ArtMethod* method, Handle<mirror::Class> annotation_class) - const SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::Object>* GetAnnotationsForMethod(ArtMethod* method) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::Class>* GetExceptionTypesForMethod(ArtMethod* method) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::Object>* GetParameterAnnotations(ArtMethod* method) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForMethod(ArtMethod* method) const - SHARED_REQUIRES(Locks::mutator_lock_); - bool IsMethodAnnotationPresent(ArtMethod* method, Handle<mirror::Class> annotation_class) const - SHARED_REQUIRES(Locks::mutator_lock_); - - const AnnotationSetItem* FindAnnotationSetForClass(Handle<mirror::Class> klass) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Object* GetAnnotationForClass(Handle<mirror::Class> klass, - Handle<mirror::Class> annotation_class) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::Object>* GetAnnotationsForClass(Handle<mirror::Class> klass) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::Class>* GetDeclaredClasses(Handle<mirror::Class> klass) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Class* GetDeclaringClass(Handle<mirror::Class> klass) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Class* GetEnclosingClass(Handle<mirror::Class> klass) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Object* GetEnclosingMethod(Handle<mirror::Class> klass) const - SHARED_REQUIRES(Locks::mutator_lock_); - bool GetInnerClass(Handle<mirror::Class> klass, mirror::String** name) const - SHARED_REQUIRES(Locks::mutator_lock_); - bool GetInnerClassFlags(Handle<mirror::Class> klass, uint32_t* flags) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::String>* GetSignatureAnnotationForClass(Handle<mirror::Class> klass) - const SHARED_REQUIRES(Locks::mutator_lock_); - bool IsClassAnnotationPresent(Handle<mirror::Class> klass, Handle<mirror::Class> annotation_class) - const SHARED_REQUIRES(Locks::mutator_lock_); - - mirror::Object* CreateAnnotationMember(Handle<mirror::Class> klass, - Handle<mirror::Class> annotation_class, - const uint8_t** annotation) const - SHARED_REQUIRES(Locks::mutator_lock_); - const AnnotationItem* GetAnnotationItemFromAnnotationSet(Handle<mirror::Class> klass, - const AnnotationSetItem* annotation_set, - uint32_t visibility, - Handle<mirror::Class> annotation_class) - const SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Object* GetAnnotationObjectFromAnnotationSet(Handle<mirror::Class> klass, - const AnnotationSetItem* annotation_set, - uint32_t visibility, - Handle<mirror::Class> annotation_class) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Object* GetAnnotationValue(Handle<mirror::Class> klass, - const AnnotationItem* annotation_item, - const char* annotation_name, - Handle<mirror::Class> array_class, - uint32_t expected_type) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::String>* GetSignatureValue(Handle<mirror::Class> klass, - const AnnotationSetItem* annotation_set) - const SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::Class>* GetThrowsValue(Handle<mirror::Class> klass, - const AnnotationSetItem* annotation_set) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::Object>* ProcessAnnotationSet(Handle<mirror::Class> klass, - const AnnotationSetItem* annotation_set, - uint32_t visibility) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::ObjectArray<mirror::Object>* ProcessAnnotationSetRefList(Handle<mirror::Class> klass, - const AnnotationSetRefList* set_ref_list, uint32_t size) const - SHARED_REQUIRES(Locks::mutator_lock_); - bool ProcessAnnotationValue(Handle<mirror::Class> klass, const uint8_t** annotation_ptr, - AnnotationValue* annotation_value, Handle<mirror::Class> return_class, - DexFile::AnnotationResultStyle result_style) const - SHARED_REQUIRES(Locks::mutator_lock_); - mirror::Object* ProcessEncodedAnnotation(Handle<mirror::Class> klass, - const uint8_t** annotation) const - SHARED_REQUIRES(Locks::mutator_lock_); - const AnnotationItem* SearchAnnotationSet(const AnnotationSetItem* annotation_set, - const char* descriptor, uint32_t visibility) const - SHARED_REQUIRES(Locks::mutator_lock_); - const uint8_t* SearchEncodedAnnotation(const uint8_t* annotation, const char* name) const - SHARED_REQUIRES(Locks::mutator_lock_); - bool SkipAnnotationValue(const uint8_t** annotation_ptr) const - SHARED_REQUIRES(Locks::mutator_lock_); - // Debug info opcodes and constants enum { DBG_END_SEQUENCE = 0x00, @@ -1099,17 +1022,6 @@ class DexFile { DISALLOW_COPY_AND_ASSIGN(LineNumFromPcContext); }; - // Determine the source file line number based on the program counter. - // "pc" is an offset, in 16-bit units, from the start of the method's code. - // - // Returns -1 if no match was found (possibly because the source files were - // compiled without "-g", so no line number information is present). - // Returns -2 for native methods (as expected in exception traces). - // - // This is used by runtime; therefore use art::Method not art::DexFile::Method. - int32_t GetLineNumFromPC(ArtMethod* method, uint32_t rel_pc) const - SHARED_REQUIRES(Locks::mutator_lock_); - // Returns false if there is no debugging information or if it cannot be decoded. bool DecodeDebugLocalInfo(const CodeItem* code_item, bool is_static, uint32_t method_idx, DexDebugNewLocalCb local_cb, void* context) const; @@ -1119,7 +1031,7 @@ class DexFile { void* context) const; const char* GetSourceFile(const ClassDef& class_def) const { - if (class_def.source_file_idx_ == 0xffffffff) { + if (!class_def.source_file_idx_.IsValid()) { return nullptr; } else { return StringDataByIdx(class_def.source_file_idx_); @@ -1169,20 +1081,33 @@ class DexFile { return oat_dex_file_; } - TypeLookupTable* GetTypeLookupTable() const { - return lookup_table_.get(); + // Used by oat writer. + void SetOatDexFile(OatDexFile* oat_dex_file) const { + oat_dex_file_ = oat_dex_file; } - void CreateTypeLookupTable(uint8_t* storage = nullptr) const; + // Utility methods for reading integral values from a buffer. + static int32_t ReadSignedInt(const uint8_t* ptr, int zwidth); + static uint32_t ReadUnsignedInt(const uint8_t* ptr, int zwidth, bool fill_on_right); + static int64_t ReadSignedLong(const uint8_t* ptr, int zwidth); + static uint64_t ReadUnsignedLong(const uint8_t* ptr, int zwidth, bool fill_on_right); - private: - // Opens a .dex file - static std::unique_ptr<const DexFile> OpenFile(int fd, const char* location, - bool verify, std::string* error_msg); + // Recalculates the checksum of the dex file. Does not use the current value in the header. + uint32_t CalculateChecksum() const; - // Opens dex files from within a .jar, .zip, or .apk file - static bool OpenZip(int fd, const std::string& location, std::string* error_msg, - std::vector<std::unique_ptr<const DexFile>>* dex_files); + // Returns a human-readable form of the method at an index. + std::string PrettyMethod(uint32_t method_idx, bool with_signature = true) const; + // Returns a human-readable form of the field at an index. + std::string PrettyField(uint32_t field_idx, bool with_type = true) const; + // Returns a human-readable form of the type at an index. + std::string PrettyType(dex::TypeIndex type_idx) const; + + private: + static std::unique_ptr<const DexFile> OpenFile(int fd, + const std::string& location, + bool verify, + bool verify_checksum, + std::string* error_msg); enum class ZipOpenErrorCode { // private kNoError, @@ -1193,31 +1118,52 @@ class DexFile { kVerifyError }; + // Open all classesXXX.dex files from a zip archive. + static bool OpenAllDexFilesFromZip(const ZipArchive& zip_archive, + const std::string& location, + bool verify_checksum, + std::string* error_msg, + std::vector<std::unique_ptr<const DexFile>>* dex_files); + // Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null // return. - static std::unique_ptr<const DexFile> Open(const ZipArchive& zip_archive, const char* entry_name, - const std::string& location, std::string* error_msg, - ZipOpenErrorCode* error_code); + static std::unique_ptr<const DexFile> OpenOneDexFileFromZip(const ZipArchive& zip_archive, + const char* entry_name, + const std::string& location, + bool verify_checksum, + std::string* error_msg, + ZipOpenErrorCode* error_code); + + enum class VerifyResult { // private + kVerifyNotAttempted, + kVerifySucceeded, + kVerifyFailed + }; + + static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base, + size_t size, + const std::string& location, + uint32_t location_checksum, + const OatDexFile* oat_dex_file, + bool verify, + bool verify_checksum, + std::string* error_msg, + VerifyResult* verify_result = nullptr); - // Opens a .dex file at the given address backed by a MemMap - static std::unique_ptr<const DexFile> OpenMemory(const std::string& location, - uint32_t location_checksum, - MemMap* mem_map, - std::string* error_msg); // Opens a .dex file at the given address, optionally backed by a MemMap static std::unique_ptr<const DexFile> OpenMemory(const uint8_t* dex_file, size_t size, const std::string& location, uint32_t location_checksum, - MemMap* mem_map, + std::unique_ptr<MemMap> mem_map, const OatDexFile* oat_dex_file, std::string* error_msg); - DexFile(const uint8_t* base, size_t size, + DexFile(const uint8_t* base, + size_t size, const std::string& location, uint32_t location_checksum, - MemMap* mem_map, const OatDexFile* oat_dex_file); // Top-level initializer that calls other Init methods. @@ -1226,10 +1172,8 @@ class DexFile { // Returns true if the header magic and version numbers are of the expected values. bool CheckMagicAndVersion(std::string* error_msg) const; - // Check whether a location denotes a multidex dex file. This is a very simple check: returns - // whether the string contains the separator character. - static bool IsMultiDexLocation(const char* location); - + // Initialize section info for sections only found in map. Returns true on success. + void InitializeSectionsFromMapList(); // The base address of the memory mapping. const uint8_t* const begin_; @@ -1269,13 +1213,25 @@ class DexFile { // Points to the base of the class definition list. const ClassDef* const class_defs_; + // Points to the base of the method handles list. + const MethodHandleItem* method_handles_; + + // Number of elements in the method handles list. + size_t num_method_handles_; + + // Points to the base of the call sites id list. + const CallSiteIdItem* call_site_ids_; + + // Number of elements in the call sites list. + size_t num_call_site_ids_; + // 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. - const OatDexFile* oat_dex_file_; - mutable std::unique_ptr<TypeLookupTable> lookup_table_; + mutable const OatDexFile* oat_dex_file_; friend class DexFileVerifierTest; + friend class OatWriter; ART_FRIEND_TEST(ClassLinkerTest, RegisterDexFileName); // for constructor }; @@ -1300,11 +1256,11 @@ class DexFileParameterIterator { bool HasNext() const { return pos_ < size_; } size_t Size() const { return size_; } void Next() { ++pos_; } - uint16_t GetTypeIdx() { + dex::TypeIndex GetTypeIdx() { return type_list_->GetTypeItem(pos_).type_idx_; } const char* GetDescriptor() { - return dex_file_.StringByTypeIdx(GetTypeIdx()); + return dex_file_.StringByTypeIdx(dex::TypeIndex(GetTypeIdx())); } private: const DexFile& dex_file_; @@ -1323,6 +1279,9 @@ class Signature : public ValueObject { return Signature(); } + bool IsVoid() const; + uint32_t GetNumberOfParameters() const; + bool operator==(const Signature& rhs) const; bool operator!=(const Signature& rhs) const { return !(*this == rhs); @@ -1368,6 +1327,9 @@ class ClassDataItemIterator { uint32_t NumVirtualMethods() const { return header_.virtual_methods_size_; } + bool IsAtMethod() const { + return pos_ >= EndOfInstanceFieldsPos(); + } bool HasNextStaticField() const { return pos_ < EndOfStaticFieldsPos(); } @@ -1532,75 +1494,82 @@ class ClassDataItemIterator { DISALLOW_IMPLICIT_CONSTRUCTORS(ClassDataItemIterator); }; -class EncodedStaticFieldValueIterator { +class EncodedArrayValueIterator { public: - // A constructor for static tools. You cannot call - // ReadValueToField() for an object created by this. - EncodedStaticFieldValueIterator(const DexFile& dex_file, - const DexFile::ClassDef& class_def); - - // A constructor meant to be called from runtime code. - EncodedStaticFieldValueIterator(const DexFile& dex_file, - Handle<mirror::DexCache>* dex_cache, - Handle<mirror::ClassLoader>* class_loader, - ClassLinker* linker, - const DexFile::ClassDef& class_def) - SHARED_REQUIRES(Locks::mutator_lock_); - - template<bool kTransactionActive> - void ReadValueToField(ArtField* field) const SHARED_REQUIRES(Locks::mutator_lock_); + EncodedArrayValueIterator(const DexFile& dex_file, const uint8_t* array_data); bool HasNext() const { return pos_ < array_size_; } void Next(); enum ValueType { - kByte = 0x00, - kShort = 0x02, - kChar = 0x03, - kInt = 0x04, - kLong = 0x06, - kFloat = 0x10, - kDouble = 0x11, - kString = 0x17, - kType = 0x18, - kField = 0x19, - kMethod = 0x1a, - kEnum = 0x1b, - kArray = 0x1c, - kAnnotation = 0x1d, - kNull = 0x1e, - kBoolean = 0x1f + kByte = 0x00, + kShort = 0x02, + kChar = 0x03, + kInt = 0x04, + kLong = 0x06, + kFloat = 0x10, + kDouble = 0x11, + kMethodType = 0x15, + kMethodHandle = 0x16, + kString = 0x17, + kType = 0x18, + kField = 0x19, + kMethod = 0x1a, + kEnum = 0x1b, + kArray = 0x1c, + kAnnotation = 0x1d, + kNull = 0x1e, + kBoolean = 0x1f, }; ValueType GetValueType() const { return type_; } const jvalue& GetJavaValue() const { return jval_; } - private: - EncodedStaticFieldValueIterator(const DexFile& dex_file, - Handle<mirror::DexCache>* dex_cache, - Handle<mirror::ClassLoader>* class_loader, - ClassLinker* linker, - const DexFile::ClassDef& class_def, - size_t pos, - ValueType type); - + protected: static constexpr uint8_t kEncodedValueTypeMask = 0x1f; // 0b11111 static constexpr uint8_t kEncodedValueArgShift = 5; const DexFile& dex_file_; - Handle<mirror::DexCache>* const dex_cache_; // Dex cache to resolve literal objects. - Handle<mirror::ClassLoader>* const class_loader_; // ClassLoader to resolve types. - ClassLinker* linker_; // Linker to resolve literal objects. size_t array_size_; // Size of array. size_t pos_; // Current position. const uint8_t* ptr_; // Pointer into encoded data array. ValueType type_; // Type of current encoded value. jvalue jval_; // Value of current encoded value. + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedArrayValueIterator); +}; +std::ostream& operator<<(std::ostream& os, const EncodedArrayValueIterator::ValueType& code); + +class EncodedStaticFieldValueIterator : public EncodedArrayValueIterator { + public: + EncodedStaticFieldValueIterator(const DexFile& dex_file, + const DexFile::ClassDef& class_def) + : EncodedArrayValueIterator(dex_file, + dex_file.GetEncodedStaticFieldValuesArray(class_def)) + {} + + private: DISALLOW_IMPLICIT_CONSTRUCTORS(EncodedStaticFieldValueIterator); }; std::ostream& operator<<(std::ostream& os, const EncodedStaticFieldValueIterator::ValueType& code); +class CallSiteArrayValueIterator : public EncodedArrayValueIterator { + public: + CallSiteArrayValueIterator(const DexFile& dex_file, + const DexFile::CallSiteIdItem& call_site_id) + : EncodedArrayValueIterator(dex_file, + dex_file.GetCallSiteEncodedValuesArray(call_site_id)) + {} + + uint32_t Size() const { return array_size_; } + + private: + DISALLOW_IMPLICIT_CONSTRUCTORS(CallSiteArrayValueIterator); +}; +std::ostream& operator<<(std::ostream& os, const CallSiteArrayValueIterator::ValueType& code); + class CatchHandlerIterator { public: CatchHandlerIterator(const DexFile::CodeItem& code_item, uint32_t address); @@ -1612,7 +1581,7 @@ class CatchHandlerIterator { Init(handler_data); } - uint16_t GetHandlerTypeIndex() const { + dex::TypeIndex GetHandlerTypeIndex() const { return handler_.type_idx_; } uint32_t GetHandlerAddress() const { @@ -1633,7 +1602,7 @@ class CatchHandlerIterator { void Init(const uint8_t* handler_data); struct CatchHandlerItem { - uint16_t type_idx_; // type index of the caught exception type + dex::TypeIndex type_idx_; // type index of the caught exception type uint32_t address_; // handler address } handler_; const uint8_t* current_data_; // the current handler in dex file. |