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