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 #include "vdex_file.h" 18 19 #include <sys/mman.h> // For the PROT_* and MAP_* constants. 20 21 #include <memory> 22 23 #include "base/logging.h" 24 #include "base/stl_util.h" 25 #include "base/unix_file/fd_file.h" 26 #include "dex_file.h" 27 #include "dex_to_dex_decompiler.h" 28 29 namespace art { 30 31 constexpr uint8_t VdexFile::Header::kVdexInvalidMagic[4]; 32 constexpr uint8_t VdexFile::Header::kVdexMagic[4]; 33 constexpr uint8_t VdexFile::Header::kVdexVersion[4]; 34 35 bool VdexFile::Header::IsMagicValid() const { 36 return (memcmp(magic_, kVdexMagic, sizeof(kVdexMagic)) == 0); 37 } 38 39 bool VdexFile::Header::IsVersionValid() const { 40 return (memcmp(version_, kVdexVersion, sizeof(kVdexVersion)) == 0); 41 } 42 43 VdexFile::Header::Header(uint32_t number_of_dex_files, 44 uint32_t dex_size, 45 uint32_t verifier_deps_size, 46 uint32_t quickening_info_size) 47 : number_of_dex_files_(number_of_dex_files), 48 dex_size_(dex_size), 49 verifier_deps_size_(verifier_deps_size), 50 quickening_info_size_(quickening_info_size) { 51 memcpy(magic_, kVdexMagic, sizeof(kVdexMagic)); 52 memcpy(version_, kVdexVersion, sizeof(kVdexVersion)); 53 DCHECK(IsMagicValid()); 54 DCHECK(IsVersionValid()); 55 } 56 57 std::unique_ptr<VdexFile> VdexFile::Open(const std::string& vdex_filename, 58 bool writable, 59 bool low_4gb, 60 bool unquicken, 61 std::string* error_msg) { 62 if (!OS::FileExists(vdex_filename.c_str())) { 63 *error_msg = "File " + vdex_filename + " does not exist."; 64 return nullptr; 65 } 66 67 std::unique_ptr<File> vdex_file; 68 if (writable) { 69 vdex_file.reset(OS::OpenFileReadWrite(vdex_filename.c_str())); 70 } else { 71 vdex_file.reset(OS::OpenFileForReading(vdex_filename.c_str())); 72 } 73 if (vdex_file == nullptr) { 74 *error_msg = "Could not open file " + vdex_filename + 75 (writable ? " for read/write" : "for reading"); 76 return nullptr; 77 } 78 79 int64_t vdex_length = vdex_file->GetLength(); 80 if (vdex_length == -1) { 81 *error_msg = "Could not read the length of file " + vdex_filename; 82 return nullptr; 83 } 84 85 return Open(vdex_file->Fd(), vdex_length, vdex_filename, writable, low_4gb, unquicken, error_msg); 86 } 87 88 std::unique_ptr<VdexFile> VdexFile::Open(int file_fd, 89 size_t vdex_length, 90 const std::string& vdex_filename, 91 bool writable, 92 bool low_4gb, 93 bool unquicken, 94 std::string* error_msg) { 95 std::unique_ptr<MemMap> mmap(MemMap::MapFile( 96 vdex_length, 97 (writable || unquicken) ? PROT_READ | PROT_WRITE : PROT_READ, 98 unquicken ? MAP_PRIVATE : MAP_SHARED, 99 file_fd, 100 0 /* start offset */, 101 low_4gb, 102 vdex_filename.c_str(), 103 error_msg)); 104 if (mmap == nullptr) { 105 *error_msg = "Failed to mmap file " + vdex_filename + " : " + *error_msg; 106 return nullptr; 107 } 108 109 std::unique_ptr<VdexFile> vdex(new VdexFile(mmap.release())); 110 if (!vdex->IsValid()) { 111 *error_msg = "Vdex file is not valid"; 112 return nullptr; 113 } 114 115 if (unquicken) { 116 std::vector<std::unique_ptr<const DexFile>> unique_ptr_dex_files; 117 if (!vdex->OpenAllDexFiles(&unique_ptr_dex_files, error_msg)) { 118 return nullptr; 119 } 120 Unquicken(MakeNonOwningPointerVector(unique_ptr_dex_files), vdex->GetQuickeningInfo()); 121 // Update the quickening info size to pretend there isn't any. 122 reinterpret_cast<Header*>(vdex->mmap_->Begin())->quickening_info_size_ = 0; 123 } 124 125 *error_msg = "Success"; 126 return vdex; 127 } 128 129 const uint8_t* VdexFile::GetNextDexFileData(const uint8_t* cursor) const { 130 DCHECK(cursor == nullptr || (cursor > Begin() && cursor <= End())); 131 if (cursor == nullptr) { 132 // Beginning of the iteration, return the first dex file if there is one. 133 return HasDexSection() ? DexBegin() : nullptr; 134 } else { 135 // Fetch the next dex file. Return null if there is none. 136 const uint8_t* data = cursor + reinterpret_cast<const DexFile::Header*>(cursor)->file_size_; 137 return (data == DexEnd()) ? nullptr : data; 138 } 139 } 140 141 bool VdexFile::OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files, 142 std::string* error_msg) { 143 size_t i = 0; 144 for (const uint8_t* dex_file_start = GetNextDexFileData(nullptr); 145 dex_file_start != nullptr; 146 dex_file_start = GetNextDexFileData(dex_file_start), ++i) { 147 size_t size = reinterpret_cast<const DexFile::Header*>(dex_file_start)->file_size_; 148 // TODO: Supply the location information for a vdex file. 149 static constexpr char kVdexLocation[] = ""; 150 std::string location = DexFile::GetMultiDexLocation(i, kVdexLocation); 151 std::unique_ptr<const DexFile> dex(DexFile::Open(dex_file_start, 152 size, 153 location, 154 GetLocationChecksum(i), 155 nullptr /*oat_dex_file*/, 156 false /*verify*/, 157 false /*verify_checksum*/, 158 error_msg)); 159 if (dex == nullptr) { 160 return false; 161 } 162 dex_files->push_back(std::move(dex)); 163 } 164 return true; 165 } 166 167 void VdexFile::Unquicken(const std::vector<const DexFile*>& dex_files, 168 const ArrayRef<const uint8_t>& quickening_info) { 169 if (quickening_info.size() == 0) { 170 // If there is no quickening info, we bail early, as the code below expects at 171 // least the size of quickening data for each method that has a code item. 172 return; 173 } 174 const uint8_t* quickening_info_ptr = quickening_info.data(); 175 const uint8_t* const quickening_info_end = quickening_info.data() + quickening_info.size(); 176 for (const DexFile* dex_file : dex_files) { 177 for (uint32_t i = 0; i < dex_file->NumClassDefs(); ++i) { 178 const DexFile::ClassDef& class_def = dex_file->GetClassDef(i); 179 const uint8_t* class_data = dex_file->GetClassData(class_def); 180 if (class_data == nullptr) { 181 continue; 182 } 183 ClassDataItemIterator it(*dex_file, class_data); 184 // Skip fields 185 while (it.HasNextStaticField()) { 186 it.Next(); 187 } 188 while (it.HasNextInstanceField()) { 189 it.Next(); 190 } 191 192 while (it.HasNextDirectMethod()) { 193 const DexFile::CodeItem* code_item = it.GetMethodCodeItem(); 194 if (code_item != nullptr) { 195 uint32_t quickening_size = *reinterpret_cast<const uint32_t*>(quickening_info_ptr); 196 quickening_info_ptr += sizeof(uint32_t); 197 optimizer::ArtDecompileDEX(*code_item, 198 ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), 199 /* decompile_return_instruction */ false); 200 quickening_info_ptr += quickening_size; 201 } 202 it.Next(); 203 } 204 205 while (it.HasNextVirtualMethod()) { 206 const DexFile::CodeItem* code_item = it.GetMethodCodeItem(); 207 if (code_item != nullptr) { 208 uint32_t quickening_size = *reinterpret_cast<const uint32_t*>(quickening_info_ptr); 209 quickening_info_ptr += sizeof(uint32_t); 210 optimizer::ArtDecompileDEX(*code_item, 211 ArrayRef<const uint8_t>(quickening_info_ptr, quickening_size), 212 /* decompile_return_instruction */ false); 213 quickening_info_ptr += quickening_size; 214 } 215 it.Next(); 216 } 217 DCHECK(!it.HasNext()); 218 } 219 } 220 if (quickening_info_ptr != quickening_info_end) { 221 LOG(FATAL) << "Failed to use all quickening info"; 222 } 223 } 224 225 } // namespace art 226