• 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