1 /* 2 * Copyright (C) 2017 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_DEX_FILE_LOADER_H_ 18 #define ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_ 19 20 #include <cstdint> 21 #include <functional> 22 #include <memory> 23 #include <optional> 24 #include <string> 25 #include <vector> 26 27 #include "base/os.h" 28 #include "base/unix_file/fd_file.h" 29 #include "dex_file.h" 30 31 namespace art { 32 33 class MemMap; 34 class OatDexFile; 35 class ScopedTrace; 36 class ZipArchive; 37 38 enum class DexFileLoaderErrorCode { 39 kNoError, 40 kEntryNotFound, 41 kExtractToMemoryError, 42 kDexFileError, 43 kMakeReadOnlyError, 44 kVerifyError 45 }; 46 47 // Class that is used to open dex files and deal with corresponding multidex and location logic. 48 class DexFileLoader { 49 public: 50 // name of the DexFile entry within a zip archive 51 static constexpr const char* kClassesDex = "classes.dex"; 52 53 // The separator character in MultiDex locations. 54 static constexpr char kMultiDexSeparator = '!'; 55 56 // Return true if the magic is valid for dex or cdex. 57 static bool IsMagicValid(uint32_t magic); 58 static bool IsMagicValid(const uint8_t* magic); 59 60 // Return true if the corresponding version and magic is valid. 61 static bool IsVersionAndMagicValid(const uint8_t* magic); 62 63 // Check whether a location denotes a multidex dex file. This is a very simple check: returns 64 // whether the string contains the separator character. 65 static bool IsMultiDexLocation(const char* location); 66 67 // Return the name of the index-th classes.dex in a multidex zip file. This is classes.dex for 68 // index == 0, and classes{index + 1}.dex else. 69 static std::string GetMultiDexClassesDexName(size_t index); 70 71 // Return the (possibly synthetic) dex location for a multidex entry. This is dex_location for 72 // index == 0, and dex_location + multi-dex-separator + GetMultiDexClassesDexName(index) else. 73 static std::string GetMultiDexLocation(size_t index, const char* dex_location); 74 75 // Returns the canonical form of the given dex location. 76 // 77 // There are different flavors of "dex locations" as follows: 78 // the file name of a dex file: 79 // The actual file path that the dex file has on disk. 80 // dex_location: 81 // This acts as a key for the class linker to know which dex file to load. 82 // It may correspond to either an old odex file or a particular dex file 83 // inside an oat file. In the first case it will also match the file name 84 // of the dex file. In the second case (oat) it will include the file name 85 // and possibly some multidex annotation to uniquely identify it. 86 // canonical_dex_location: 87 // the dex_location where its file name part has been made canonical. 88 static std::string GetDexCanonicalLocation(const char* dex_location); 89 90 // For normal dex files, location and base location coincide. If a dex file is part of a multidex 91 // archive, the base location is the name of the originating jar/apk, stripped of any internal 92 // classes*.dex path. GetBaseLocation(const char * location)93 static std::string GetBaseLocation(const char* location) { 94 const char* pos = strrchr(location, kMultiDexSeparator); 95 return (pos == nullptr) ? location : std::string(location, pos - location); 96 } 97 GetBaseLocation(const std::string & location)98 static std::string GetBaseLocation(const std::string& location) { 99 return GetBaseLocation(location.c_str()); 100 } 101 102 // Returns the '!classes*.dex' part of the dex location. Returns an empty 103 // string if there is no multidex suffix for the given location. 104 // The kMultiDexSeparator is included in the returned suffix. GetMultiDexSuffix(const std::string & location)105 static std::string GetMultiDexSuffix(const std::string& location) { 106 size_t pos = location.rfind(kMultiDexSeparator); 107 return (pos == std::string::npos) ? std::string() : location.substr(pos); 108 } 109 DexFileLoader(const char * filename,int fd,const std::string & location)110 DexFileLoader(const char* filename, int fd, const std::string& location) 111 : filename_(filename), 112 file_(fd == -1 ? std::optional<File>() : File(fd, /*check_usage=*/false)), 113 location_(location) {} 114 DexFileLoader(std::shared_ptr<DexFileContainer> container,const std::string & location)115 DexFileLoader(std::shared_ptr<DexFileContainer> container, const std::string& location) 116 : root_container_(std::move(container)), location_(location) { 117 DCHECK(root_container_ != nullptr); 118 } 119 120 DexFileLoader(const uint8_t* base, size_t size, const std::string& location); 121 122 DexFileLoader(std::vector<uint8_t>&& memory, const std::string& location); 123 124 DexFileLoader(MemMap&& mem_map, const std::string& location); 125 DexFileLoader(int fd,const std::string & location)126 DexFileLoader(int fd, const std::string& location) 127 : DexFileLoader(/*filename=*/location.c_str(), fd, location) {} 128 DexFileLoader(const char * filename,const std::string & location)129 DexFileLoader(const char* filename, const std::string& location) 130 : DexFileLoader(filename, /*fd=*/-1, location) {} 131 DexFileLoader(const std::string & location)132 explicit DexFileLoader(const std::string& location) 133 : DexFileLoader(location.c_str(), /*fd=*/-1, location) {} 134 ~DexFileLoader()135 virtual ~DexFileLoader() {} 136 137 std::unique_ptr<const DexFile> Open(uint32_t location_checksum, 138 const OatDexFile* oat_dex_file, 139 bool verify, 140 bool verify_checksum, 141 std::string* error_msg); 142 Open(uint32_t location_checksum,bool verify,bool verify_checksum,std::string * error_msg)143 std::unique_ptr<const DexFile> Open(uint32_t location_checksum, 144 bool verify, 145 bool verify_checksum, 146 std::string* error_msg) { 147 return Open(location_checksum, 148 /*oat_dex_file=*/nullptr, 149 verify, 150 verify_checksum, 151 error_msg); 152 } 153 154 // Opens all dex files, guessing the container format based on file magic. 155 bool Open(bool verify, 156 bool verify_checksum, 157 bool allow_no_dex_files, 158 DexFileLoaderErrorCode* error_code, 159 std::string* error_msg, 160 std::vector<std::unique_ptr<const DexFile>>* dex_files); 161 Open(bool verify,bool verify_checksum,DexFileLoaderErrorCode * error_code,std::string * error_msg,std::vector<std::unique_ptr<const DexFile>> * dex_files)162 bool Open(bool verify, 163 bool verify_checksum, 164 DexFileLoaderErrorCode* error_code, 165 std::string* error_msg, 166 std::vector<std::unique_ptr<const DexFile>>* dex_files) { 167 return Open(verify, 168 verify_checksum, 169 /*allow_no_dex_files=*/false, 170 error_code, 171 error_msg, 172 dex_files); 173 } 174 Open(bool verify,bool verify_checksum,bool allow_no_dex_files,std::string * error_msg,std::vector<std::unique_ptr<const DexFile>> * dex_files)175 bool Open(bool verify, 176 bool verify_checksum, 177 bool allow_no_dex_files, 178 std::string* error_msg, 179 std::vector<std::unique_ptr<const DexFile>>* dex_files) { 180 DexFileLoaderErrorCode error_code; 181 return Open(verify, verify_checksum, allow_no_dex_files, &error_code, error_msg, dex_files); 182 } 183 Open(bool verify,bool verify_checksum,std::string * error_msg,std::vector<std::unique_ptr<const DexFile>> * dex_files)184 bool Open(bool verify, 185 bool verify_checksum, 186 std::string* error_msg, 187 std::vector<std::unique_ptr<const DexFile>>* dex_files) { 188 DexFileLoaderErrorCode error_code; 189 return Open(verify, 190 verify_checksum, 191 /*allow_no_dex_files=*/false, 192 &error_code, 193 error_msg, 194 dex_files); 195 } 196 197 protected: 198 bool InitAndReadMagic(uint32_t* magic, std::string* error_msg); 199 200 // Ensure we have root container. If we are backed by a file, memory-map it. 201 // We can only do this for dex files since zip files might be too big to map. 202 bool MapRootContainer(std::string* error_msg); 203 204 static std::unique_ptr<DexFile> OpenCommon(std::shared_ptr<DexFileContainer> container, 205 const uint8_t* base, 206 size_t size, 207 const std::string& location, 208 std::optional<uint32_t> location_checksum, 209 const OatDexFile* oat_dex_file, 210 bool verify, 211 bool verify_checksum, 212 std::string* error_msg, 213 DexFileLoaderErrorCode* error_code); 214 215 // Old signature preserved for app-compat. 216 std::unique_ptr<const DexFile> Open(const uint8_t* base, 217 size_t size, 218 const std::string& location, 219 uint32_t location_checksum, 220 const OatDexFile* oat_dex_file, 221 bool verify, 222 bool verify_checksum, 223 std::string* error_msg, 224 std::unique_ptr<DexFileContainer> container) const; 225 226 // Old signature preserved for app-compat. 227 enum VerifyResult {}; 228 static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base, 229 size_t size, 230 const uint8_t* data_base, 231 size_t data_size, 232 const std::string& location, 233 uint32_t location_checksum, 234 const OatDexFile* oat_dex_file, 235 bool verify, 236 bool verify_checksum, 237 std::string* error_msg, 238 std::unique_ptr<DexFileContainer> container, 239 VerifyResult* verify_result); 240 241 // Open .dex files from the entry_name in a zip archive. 242 bool OpenFromZipEntry(const ZipArchive& zip_archive, 243 const char* entry_name, 244 const std::string& location, 245 bool verify, 246 bool verify_checksum, 247 DexFileLoaderErrorCode* error_code, 248 std::string* error_msg, 249 std::vector<std::unique_ptr<const DexFile>>* dex_files) const; 250 251 // The DexFileLoader can be backed either by file or by memory (i.e. DexFileContainer). 252 // We can not just mmap the file since APKs might be unreasonably large for 32-bit system. 253 std::string filename_; 254 std::optional<File> file_; 255 std::shared_ptr<DexFileContainer> root_container_; 256 const std::string location_; 257 }; 258 259 } // namespace art 260 261 #endif // ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_ 262