• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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