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 // QuickeningInfo 43 // uint8[] quickening data 44 // unaligned_uint32_t[2][] table of offsets pair: 45 // uint32_t[0] contains code_item_offset 46 // uint32_t[1] contains quickening data offset from the start 47 // of QuickeningInfo 48 // unalgined_uint32_t[D] start offsets (from the start of QuickeningInfo) in previous 49 // table for each dex file 50 51 class VdexFile { 52 public: 53 struct Header { 54 public: 55 Header(uint32_t number_of_dex_files_, 56 uint32_t dex_size, 57 uint32_t verifier_deps_size, 58 uint32_t quickening_info_size); 59 GetMagicHeader60 const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); } GetVersionHeader61 const char* GetVersion() const { return reinterpret_cast<const char*>(version_); } 62 bool IsMagicValid() const; 63 bool IsVersionValid() const; IsValidHeader64 bool IsValid() const { return IsMagicValid() && IsVersionValid(); } 65 GetDexSizeHeader66 uint32_t GetDexSize() const { return dex_size_; } GetVerifierDepsSizeHeader67 uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; } GetQuickeningInfoSizeHeader68 uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; } GetNumberOfDexFilesHeader69 uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; } 70 71 static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' }; 72 73 private: 74 static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' }; 75 // Last update: Use set for unverified_classes_. 76 static constexpr uint8_t kVdexVersion[] = { '0', '1', '0', '\0' }; 77 78 uint8_t magic_[4]; 79 uint8_t version_[4]; 80 uint32_t number_of_dex_files_; 81 uint32_t dex_size_; 82 uint32_t verifier_deps_size_; 83 uint32_t quickening_info_size_; 84 85 friend class VdexFile; 86 }; 87 88 typedef uint32_t VdexChecksum; 89 90 // Returns nullptr if the vdex file cannot be opened or is not valid. 91 static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename, 92 bool writable, 93 bool low_4gb, 94 bool unquicken, 95 std::string* error_msg); 96 97 // Returns nullptr if the vdex file cannot be opened or is not valid. 98 static std::unique_ptr<VdexFile> Open(int file_fd, 99 size_t vdex_length, 100 const std::string& vdex_filename, 101 bool writable, 102 bool low_4gb, 103 bool unquicken, 104 std::string* error_msg); 105 Begin()106 const uint8_t* Begin() const { return mmap_->Begin(); } End()107 const uint8_t* End() const { return mmap_->End(); } Size()108 size_t Size() const { return mmap_->Size(); } 109 GetHeader()110 const Header& GetHeader() const { 111 return *reinterpret_cast<const Header*>(Begin()); 112 } 113 GetVerifierDepsData()114 ArrayRef<const uint8_t> GetVerifierDepsData() const { 115 return ArrayRef<const uint8_t>( 116 DexBegin() + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize()); 117 } 118 GetQuickeningInfo()119 ArrayRef<const uint8_t> GetQuickeningInfo() const { 120 return ArrayRef<const uint8_t>( 121 GetVerifierDepsData().data() + GetHeader().GetVerifierDepsSize(), 122 GetHeader().GetQuickeningInfoSize()); 123 } 124 IsValid()125 bool IsValid() const { 126 return mmap_->Size() >= sizeof(Header) && GetHeader().IsValid(); 127 } 128 129 // This method is for iterating over the dex files in the vdex. If `cursor` is null, 130 // the first dex file is returned. If `cursor` is not null, it must point to a dex 131 // file and this method returns the next dex file if there is one, or null if there 132 // is none. 133 const uint8_t* GetNextDexFileData(const uint8_t* cursor) const; 134 135 // Get the location checksum of the dex file number `dex_file_index`. GetLocationChecksum(uint32_t dex_file_index)136 uint32_t GetLocationChecksum(uint32_t dex_file_index) const { 137 DCHECK_LT(dex_file_index, GetHeader().GetNumberOfDexFiles()); 138 return reinterpret_cast<const uint32_t*>(Begin() + sizeof(Header))[dex_file_index]; 139 } 140 141 // Open all the dex files contained in this vdex file. 142 bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files, 143 std::string* error_msg); 144 145 // In-place unquicken the given `dex_files` based on `quickening_info`. 146 static void Unquicken(const std::vector<const DexFile*>& dex_files, 147 const ArrayRef<const uint8_t>& quickening_info); 148 149 // Fully unquicken `target_dex_file` based on quickening info stored 150 // in this vdex file for `original_dex_file`. 151 void FullyUnquickenDexFile(const DexFile& target_dex_file, 152 const DexFile& original_dex_file) const; 153 154 // Return the quickening info of the given code item. 155 const uint8_t* GetQuickenedInfoOf(const DexFile& dex_file, uint32_t code_item_offset) const; 156 157 private: VdexFile(MemMap * mmap)158 explicit VdexFile(MemMap* mmap) : mmap_(mmap) {} 159 HasDexSection()160 bool HasDexSection() const { 161 return GetHeader().GetDexSize() != 0; 162 } 163 DexBegin()164 const uint8_t* DexBegin() const { 165 return Begin() + sizeof(Header) + GetSizeOfChecksumsSection(); 166 } 167 DexEnd()168 const uint8_t* DexEnd() const { 169 return DexBegin() + GetHeader().GetDexSize(); 170 } 171 GetSizeOfChecksumsSection()172 size_t GetSizeOfChecksumsSection() const { 173 return sizeof(VdexChecksum) * GetHeader().GetNumberOfDexFiles(); 174 } 175 176 uint32_t GetDexFileIndex(const DexFile& dex_file) const; 177 178 std::unique_ptr<MemMap> mmap_; 179 180 DISALLOW_COPY_AND_ASSIGN(VdexFile); 181 }; 182 183 } // namespace art 184 185 #endif // ART_RUNTIME_VDEX_FILE_H_ 186