1 /*
2  * Copyright (C) 2016 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_RUNTIME_VDEX_FILE_H_
18 #define ART_RUNTIME_VDEX_FILE_H_
19 
20 #include <stdint.h>
21 #include <string>
22 
23 #include "base/array_ref.h"
24 #include "base/macros.h"
25 #include "mem_map.h"
26 #include "os.h"
27 
28 namespace art {
29 
30 class DexFile;
31 
32 // VDEX files contain extracted DEX files. The VdexFile class maps the file to
33 // memory and provides tools for accessing its individual sections.
34 //
35 // File format:
36 //   VdexFile::Header    fixed-length header
37 //
38 //   DEX[0]              array of the input DEX files
39 //   DEX[1]              the bytecode may have been quickened
40 //   ...
41 //   DEX[D]
42 //
43 
44 class VdexFile {
45  public:
46   struct Header {
47    public:
48     Header(uint32_t number_of_dex_files_,
49            uint32_t dex_size,
50            uint32_t verifier_deps_size,
51            uint32_t quickening_info_size);
52 
GetMagicHeader53     const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
GetVersionHeader54     const char* GetVersion() const { return reinterpret_cast<const char*>(version_); }
55     bool IsMagicValid() const;
56     bool IsVersionValid() const;
IsValidHeader57     bool IsValid() const { return IsMagicValid() && IsVersionValid(); }
58 
GetDexSizeHeader59     uint32_t GetDexSize() const { return dex_size_; }
GetVerifierDepsSizeHeader60     uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
GetQuickeningInfoSizeHeader61     uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; }
GetNumberOfDexFilesHeader62     uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; }
63 
64     static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' };
65 
66    private:
67     static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
68     // Last update: Disable in-place vdex update
69     static constexpr uint8_t kVdexVersion[] = { '0', '0', '6', '\0' };
70 
71     uint8_t magic_[4];
72     uint8_t version_[4];
73     uint32_t number_of_dex_files_;
74     uint32_t dex_size_;
75     uint32_t verifier_deps_size_;
76     uint32_t quickening_info_size_;
77 
78     friend class VdexFile;
79   };
80 
81   typedef uint32_t VdexChecksum;
82 
83   // Returns nullptr if the vdex file cannot be opened or is not valid.
84   static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename,
85                                         bool writable,
86                                         bool low_4gb,
87                                         bool unquicken,
88                                         std::string* error_msg);
89 
90   // Returns nullptr if the vdex file cannot be opened or is not valid.
91   static std::unique_ptr<VdexFile> Open(int file_fd,
92                                         size_t vdex_length,
93                                         const std::string& vdex_filename,
94                                         bool writable,
95                                         bool low_4gb,
96                                         bool unquicken,
97                                         std::string* error_msg);
98 
Begin()99   const uint8_t* Begin() const { return mmap_->Begin(); }
End()100   const uint8_t* End() const { return mmap_->End(); }
Size()101   size_t Size() const { return mmap_->Size(); }
102 
GetHeader()103   const Header& GetHeader() const {
104     return *reinterpret_cast<const Header*>(Begin());
105   }
106 
GetVerifierDepsData()107   ArrayRef<const uint8_t> GetVerifierDepsData() const {
108     return ArrayRef<const uint8_t>(
109         DexBegin() + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize());
110   }
111 
GetQuickeningInfo()112   ArrayRef<const uint8_t> GetQuickeningInfo() const {
113     return ArrayRef<const uint8_t>(
114         GetVerifierDepsData().data() + GetHeader().GetVerifierDepsSize(),
115         GetHeader().GetQuickeningInfoSize());
116   }
117 
IsValid()118   bool IsValid() const {
119     return mmap_->Size() >= sizeof(Header) && GetHeader().IsValid();
120   }
121 
122   // This method is for iterating over the dex files in the vdex. If `cursor` is null,
123   // the first dex file is returned. If `cursor` is not null, it must point to a dex
124   // file and this method returns the next dex file if there is one, or null if there
125   // is none.
126   const uint8_t* GetNextDexFileData(const uint8_t* cursor) const;
127 
128   // Get the location checksum of the dex file number `dex_file_index`.
GetLocationChecksum(uint32_t dex_file_index)129   uint32_t GetLocationChecksum(uint32_t dex_file_index) const {
130     DCHECK_LT(dex_file_index, GetHeader().GetNumberOfDexFiles());
131     return reinterpret_cast<const uint32_t*>(Begin() + sizeof(Header))[dex_file_index];
132   }
133 
134   // Opens all the dex files contained in this vdex file.
135   bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
136                        std::string* error_msg);
137 
138   // In-place unquicken the given `dex_files` based on `quickening_info`.
139   static void Unquicken(const std::vector<const DexFile*>& dex_files,
140                         const ArrayRef<const uint8_t>& quickening_info);
141 
142  private:
VdexFile(MemMap * mmap)143   explicit VdexFile(MemMap* mmap) : mmap_(mmap) {}
144 
HasDexSection()145   bool HasDexSection() const {
146     return GetHeader().GetDexSize() != 0;
147   }
148 
DexBegin()149   const uint8_t* DexBegin() const {
150     return Begin() + sizeof(Header) + GetSizeOfChecksumsSection();
151   }
152 
DexEnd()153   const uint8_t* DexEnd() const {
154     return DexBegin() + GetHeader().GetDexSize();
155   }
156 
GetSizeOfChecksumsSection()157   size_t GetSizeOfChecksumsSection() const {
158     return sizeof(VdexChecksum) * GetHeader().GetNumberOfDexFiles();
159   }
160 
161   std::unique_ptr<MemMap> mmap_;
162 
163   DISALLOW_COPY_AND_ASSIGN(VdexFile);
164 };
165 
166 }  // namespace art
167 
168 #endif  // ART_RUNTIME_VDEX_FILE_H_
169