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 <memory>
22 #include <string>
23 #include <vector>
24 
25 namespace art {
26 
27 class DexFile;
28 class DexFileContainer;
29 class MemMap;
30 class OatDexFile;
31 
32 class DexZipArchive;
33 
34 // Class that is used to open dex files and deal with corresponding multidex and location logic.
35 class DexFileLoader {
36  public:
37   // name of the DexFile entry within a zip archive
38   static constexpr const char* kClassesDex = "classes.dex";
39 
40   // The separator character in MultiDex locations.
41   static constexpr char kMultiDexSeparator = '!';
42 
43   // Return true if the magic is valid for dex or cdex.
44   static bool IsMagicValid(uint32_t magic);
45   static bool IsMagicValid(const uint8_t* magic);
46 
47   // Return true if the corresponding version and magic is valid.
48   static bool IsVersionAndMagicValid(const uint8_t* magic);
49 
50   // Check whether a location denotes a multidex dex file. This is a very simple check: returns
51   // whether the string contains the separator character.
52   static bool IsMultiDexLocation(const char* location);
53 
54   // Return the name of the index-th classes.dex in a multidex zip file. This is classes.dex for
55   // index == 0, and classes{index + 1}.dex else.
56   static std::string GetMultiDexClassesDexName(size_t index);
57 
58   // Return the (possibly synthetic) dex location for a multidex entry. This is dex_location for
59   // index == 0, and dex_location + multi-dex-separator + GetMultiDexClassesDexName(index) else.
60   static std::string GetMultiDexLocation(size_t index, const char* dex_location);
61 
62   // Returns the canonical form of the given dex location.
63   //
64   // There are different flavors of "dex locations" as follows:
65   // the file name of a dex file:
66   //     The actual file path that the dex file has on disk.
67   // dex_location:
68   //     This acts as a key for the class linker to know which dex file to load.
69   //     It may correspond to either an old odex file or a particular dex file
70   //     inside an oat file. In the first case it will also match the file name
71   //     of the dex file. In the second case (oat) it will include the file name
72   //     and possibly some multidex annotation to uniquely identify it.
73   // canonical_dex_location:
74   //     the dex_location where its file name part has been made canonical.
75   static std::string GetDexCanonicalLocation(const char* dex_location);
76 
77   // For normal dex files, location and base location coincide. If a dex file is part of a multidex
78   // archive, the base location is the name of the originating jar/apk, stripped of any internal
79   // classes*.dex path.
GetBaseLocation(const char * location)80   static std::string GetBaseLocation(const char* location) {
81     const char* pos = strrchr(location, kMultiDexSeparator);
82     return (pos == nullptr) ? location : std::string(location, pos - location);
83   }
84 
GetBaseLocation(const std::string & location)85   static std::string GetBaseLocation(const std::string& location) {
86     return GetBaseLocation(location.c_str());
87   }
88 
89   // Returns the '!classes*.dex' part of the dex location. Returns an empty
90   // string if there is no multidex suffix for the given location.
91   // The kMultiDexSeparator is included in the returned suffix.
GetMultiDexSuffix(const std::string & location)92   static std::string GetMultiDexSuffix(const std::string& location) {
93     size_t pos = location.rfind(kMultiDexSeparator);
94     return (pos == std::string::npos) ? std::string() : location.substr(pos);
95   }
96 
~DexFileLoader()97   virtual ~DexFileLoader() { }
98 
99   // Returns the checksums of a file for comparison with GetLocationChecksum().
100   // For .dex files, this is the single header checksum.
101   // For zip files, this is the zip entry CRC32 checksum for classes.dex and
102   // each additional multidex entry classes2.dex, classes3.dex, etc.
103   // If a valid zip_fd is provided the file content will be read directly from
104   // the descriptor and `filename` will be used as alias for error logging. If
105   // zip_fd is -1, the method will try to open the `filename` and read the
106   // content from it.
107   // Return true if the checksums could be found, false otherwise.
108   virtual bool GetMultiDexChecksums(const char* filename,
109                                     std::vector<uint32_t>* checksums,
110                                     std::string* error_msg,
111                                     int zip_fd = -1,
112                                     bool* zip_file_only_contains_uncompress_dex = nullptr) const;
113 
114   // Opens .dex file, backed by existing memory
115   virtual std::unique_ptr<const DexFile> Open(const uint8_t* base,
116                                               size_t size,
117                                               const std::string& location,
118                                               uint32_t location_checksum,
119                                               const OatDexFile* oat_dex_file,
120                                               bool verify,
121                                               bool verify_checksum,
122                                               std::string* error_msg) const;
123 
124   // Open a dex file with a separate data section.
125   virtual std::unique_ptr<const DexFile> OpenWithDataSection(
126       const uint8_t* base,
127       size_t size,
128       const uint8_t* data_base,
129       size_t data_size,
130       const std::string& location,
131       uint32_t location_checksum,
132       const OatDexFile* oat_dex_file,
133       bool verify,
134       bool verify_checksum,
135       std::string* error_msg) const;
136 
137 
138   // Opens all .dex files found in the memory map, guessing the container format based on file
139   // extension.
140   virtual bool OpenAll(const uint8_t* base,
141                        size_t size,
142                        const std::string& location,
143                        bool verify,
144                        bool verify_checksum,
145                        std::string* error_msg,
146                        std::vector<std::unique_ptr<const DexFile>>* dex_files) const;
147 
148  protected:
149   enum class ZipOpenErrorCode {
150     kNoError,
151     kEntryNotFound,
152     kExtractToMemoryError,
153     kDexFileError,
154     kMakeReadOnlyError,
155     kVerifyError
156   };
157 
158   enum class VerifyResult {  // private
159     kVerifyNotAttempted,
160     kVerifySucceeded,
161     kVerifyFailed
162   };
163 
164   static std::unique_ptr<DexFile> OpenCommon(const uint8_t* base,
165                                              size_t size,
166                                              const uint8_t* data_base,
167                                              size_t data_size,
168                                              const std::string& location,
169                                              uint32_t location_checksum,
170                                              const OatDexFile* oat_dex_file,
171                                              bool verify,
172                                              bool verify_checksum,
173                                              std::string* error_msg,
174                                              std::unique_ptr<DexFileContainer> container,
175                                              VerifyResult* verify_result);
176 
177  private:
178   // Open all classesXXX.dex files from a zip archive.
179   bool OpenAllDexFilesFromZip(const DexZipArchive& zip_archive,
180                               const std::string& location,
181                               bool verify,
182                               bool verify_checksum,
183                               std::string* error_msg,
184                               std::vector<std::unique_ptr<const DexFile>>* dex_files) const;
185 
186   // Opens .dex file from the entry_name in a zip archive. error_code is undefined when non-null
187   // return.
188   std::unique_ptr<const DexFile> OpenOneDexFileFromZip(const DexZipArchive& zip_archive,
189                                                        const char* entry_name,
190                                                        const std::string& location,
191                                                        bool verify,
192                                                        bool verify_checksum,
193                                                        std::string* error_msg,
194                                                        ZipOpenErrorCode* error_code) const;
195 };
196 
197 }  // namespace art
198 
199 #endif  // ART_LIBDEXFILE_DEX_DEX_FILE_LOADER_H_
200