1 /* 2 * Copyright (C) 2016 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_RUNTIME_VDEX_FILE_H_ 18 #define ART_RUNTIME_VDEX_FILE_H_ 19 20 #include <stdint.h> 21 #include <string> 22 23 #include "base/array_ref.h" 24 #include "base/macros.h" 25 #include "mem_map.h" 26 #include "os.h" 27 28 namespace art { 29 30 class DexFile; 31 32 // VDEX files contain extracted DEX files. The VdexFile class maps the file to 33 // memory and provides tools for accessing its individual sections. 34 // 35 // File format: 36 // VdexFile::Header fixed-length header 37 // 38 // DEX[0] array of the input DEX files 39 // DEX[1] the bytecode may have been quickened 40 // ... 41 // DEX[D] 42 // 43 44 class VdexFile { 45 public: 46 struct Header { 47 public: 48 Header(uint32_t number_of_dex_files_, 49 uint32_t dex_size, 50 uint32_t verifier_deps_size, 51 uint32_t quickening_info_size); 52 GetMagicHeader53 const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); } GetVersionHeader54 const char* GetVersion() const { return reinterpret_cast<const char*>(version_); } 55 bool IsMagicValid() const; 56 bool IsVersionValid() const; IsValidHeader57 bool IsValid() const { return IsMagicValid() && IsVersionValid(); } 58 GetDexSizeHeader59 uint32_t GetDexSize() const { return dex_size_; } GetVerifierDepsSizeHeader60 uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; } GetQuickeningInfoSizeHeader61 uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; } GetNumberOfDexFilesHeader62 uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; } 63 64 static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' }; 65 66 private: 67 static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' }; 68 // Last update: Disable in-place vdex update 69 static constexpr uint8_t kVdexVersion[] = { '0', '0', '6', '\0' }; 70 71 uint8_t magic_[4]; 72 uint8_t version_[4]; 73 uint32_t number_of_dex_files_; 74 uint32_t dex_size_; 75 uint32_t verifier_deps_size_; 76 uint32_t quickening_info_size_; 77 78 friend class VdexFile; 79 }; 80 81 typedef uint32_t VdexChecksum; 82 83 // Returns nullptr if the vdex file cannot be opened or is not valid. 84 static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename, 85 bool writable, 86 bool low_4gb, 87 bool unquicken, 88 std::string* error_msg); 89 90 // Returns nullptr if the vdex file cannot be opened or is not valid. 91 static std::unique_ptr<VdexFile> Open(int file_fd, 92 size_t vdex_length, 93 const std::string& vdex_filename, 94 bool writable, 95 bool low_4gb, 96 bool unquicken, 97 std::string* error_msg); 98 Begin()99 const uint8_t* Begin() const { return mmap_->Begin(); } End()100 const uint8_t* End() const { return mmap_->End(); } Size()101 size_t Size() const { return mmap_->Size(); } 102 GetHeader()103 const Header& GetHeader() const { 104 return *reinterpret_cast<const Header*>(Begin()); 105 } 106 GetVerifierDepsData()107 ArrayRef<const uint8_t> GetVerifierDepsData() const { 108 return ArrayRef<const uint8_t>( 109 DexBegin() + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize()); 110 } 111 GetQuickeningInfo()112 ArrayRef<const uint8_t> GetQuickeningInfo() const { 113 return ArrayRef<const uint8_t>( 114 GetVerifierDepsData().data() + GetHeader().GetVerifierDepsSize(), 115 GetHeader().GetQuickeningInfoSize()); 116 } 117 IsValid()118 bool IsValid() const { 119 return mmap_->Size() >= sizeof(Header) && GetHeader().IsValid(); 120 } 121 122 // This method is for iterating over the dex files in the vdex. If `cursor` is null, 123 // the first dex file is returned. If `cursor` is not null, it must point to a dex 124 // file and this method returns the next dex file if there is one, or null if there 125 // is none. 126 const uint8_t* GetNextDexFileData(const uint8_t* cursor) const; 127 128 // Get the location checksum of the dex file number `dex_file_index`. GetLocationChecksum(uint32_t dex_file_index)129 uint32_t GetLocationChecksum(uint32_t dex_file_index) const { 130 DCHECK_LT(dex_file_index, GetHeader().GetNumberOfDexFiles()); 131 return reinterpret_cast<const uint32_t*>(Begin() + sizeof(Header))[dex_file_index]; 132 } 133 134 // Opens all the dex files contained in this vdex file. 135 bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files, 136 std::string* error_msg); 137 138 // In-place unquicken the given `dex_files` based on `quickening_info`. 139 static void Unquicken(const std::vector<const DexFile*>& dex_files, 140 const ArrayRef<const uint8_t>& quickening_info); 141 142 private: VdexFile(MemMap * mmap)143 explicit VdexFile(MemMap* mmap) : mmap_(mmap) {} 144 HasDexSection()145 bool HasDexSection() const { 146 return GetHeader().GetDexSize() != 0; 147 } 148 DexBegin()149 const uint8_t* DexBegin() const { 150 return Begin() + sizeof(Header) + GetSizeOfChecksumsSection(); 151 } 152 DexEnd()153 const uint8_t* DexEnd() const { 154 return DexBegin() + GetHeader().GetDexSize(); 155 } 156 GetSizeOfChecksumsSection()157 size_t GetSizeOfChecksumsSection() const { 158 return sizeof(VdexChecksum) * GetHeader().GetNumberOfDexFiles(); 159 } 160 161 std::unique_ptr<MemMap> mmap_; 162 163 DISALLOW_COPY_AND_ASSIGN(VdexFile); 164 }; 165 166 } // namespace art 167 168 #endif // ART_RUNTIME_VDEX_FILE_H_ 169