/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_ #define ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_ #include <cstdint> #include <memory> #include <string> #include <vector> namespace art { class DexFile; class DexFileContainer; class MemMap; class OatDexFile; class DexZipArchive; enum class DexFileLoaderErrorCode { kNoError, kEntryNotFound, kExtractToMemoryError, kDexFileError, kMakeReadOnlyError, kVerifyError }; // Class that is used to open dex files and deal with corresponding multidex and location logic. class DexFileLoader { public: // name of the DexFile entry within a zip archive static constexpr const char* kClassesDex = "classes.dex"; // The separator character in MultiDex locations. static constexpr char kMultiDexSeparator = '!'; // Return true if the magic is valid for dex or cdex. static bool IsMagicValid(uint32_t magic); static bool IsMagicValid(const uint8_t* magic); // Return true if the corresponding version and magic is valid. static bool IsVersionAndMagicValid(const uint8_t* magic); // 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); // Return the name of the index-th classes.dex in a multidex zip file. This is classes.dex for // index == 0, and classes{index + 1}.dex else. static std::string GetMultiDexClassesDexName(size_t index); // Return the (possibly synthetic) dex location for a multidex entry. This is dex_location for // index == 0, and dex_location + multi-dex-separator + GetMultiDexClassesDexName(index) else. static std::string GetMultiDexLocation(size_t index, const char* dex_location); // Returns the canonical form of the given dex location. // // There are different flavors of "dex locations" as follows: // the file name of a dex file: // The actual file path that the dex file has on disk. // dex_location: // This acts as a key for the class linker to know which dex file to load. // It may correspond to either an old odex file or a particular dex file // inside an oat file. In the first case it will also match the file name // of the dex file. In the second case (oat) it will include the file name // and possibly some multidex annotation to uniquely identify it. // canonical_dex_location: // the dex_location where its file name part has been made canonical. static std::string GetDexCanonicalLocation(const char* dex_location); // For normal dex files, location and base location coincide. If a dex file is part of a multidex // archive, the base location is the name of the originating jar/apk, stripped of any internal // classes*.dex path. static std::string GetBaseLocation(const char* location) { const char* pos = strrchr(location, kMultiDexSeparator); return (pos == nullptr) ? location : std::string(location, pos - location); } static std::string GetBaseLocation(const std::string& location) { return GetBaseLocation(location.c_str()); } // Returns the '!classes*.dex' part of the dex location. Returns an empty // string if there is no multidex suffix for the given location. // The kMultiDexSeparator is included in the returned suffix. static std::string GetMultiDexSuffix(const std::string& location) { size_t pos = location.rfind(kMultiDexSeparator); return (pos == std::string::npos) ? std::string() : location.substr(pos); } virtual ~DexFileLoader() { } // 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. // If a valid zip_fd is provided the file content will be read directly from // the descriptor and `filename` will be used as alias for error logging. If // zip_fd is -1, the method will try to open the `filename` and read the // content from it. // Return true if the checksums could be found, false otherwise. virtual bool GetMultiDexChecksums(const char* filename, std::vector<uint32_t>* checksums, std::string* error_msg, int zip_fd = -1, bool* zip_file_only_contains_uncompress_dex = nullptr) const; // Opens .dex file, backed by existing memory virtual 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, std::unique_ptr<DexFileContainer> container = nullptr) const; // Open a dex file with a separate data section. virtual std::unique_ptr<const DexFile> OpenWithDataSection( const uint8_t* base, size_t size, const uint8_t* data_base, size_t data_size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum, std::string* error_msg) const; // Opens all .dex files found in the memory map, guessing the container format based on file // extension. virtual bool OpenAll(const uint8_t* base, size_t size, const std::string& location, bool verify, bool verify_checksum, DexFileLoaderErrorCode* error_code, std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files) const; protected: enum class VerifyResult { // private kVerifyNotAttempted, kVerifySucceeded, kVerifyFailed }; static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base, size_t size, const uint8_t* data_base, size_t data_size, const std::string& location, uint32_t location_checksum, const OatDexFile* oat_dex_file, bool verify, bool verify_checksum, std::string* error_msg, std::unique_ptr<DexFileContainer> container, VerifyResult* verify_result); private: // Open all classesXXX.dex files from a zip archive. bool OpenAllDexFilesFromZip(const DexZipArchive& zip_archive, const std::string& location, bool verify, bool verify_checksum, DexFileLoaderErrorCode* error_code, std::string* error_msg, std::vector<std::unique_ptr<const DexFile>>* dex_files) const; // Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null // return. std::unique_ptr<const DexFile> OpenOneDexFileFromZip(const DexZipArchive& zip_archive, const char* entry_name, const std::string& location, bool verify, bool verify_checksum, DexFileLoaderErrorCode* error_code, std::string* error_msg) const; }; } // namespace art #endif // ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_