• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //   QuickeningInfo
43 //     uint8[]                     quickening data
44 //     unaligned_uint32_t[2][]     table of offsets pair:
45 //                                    uint32_t[0] contains code_item_offset
46 //                                    uint32_t[1] contains quickening data offset from the start
47 //                                                of QuickeningInfo
48 //     unalgined_uint32_t[D]       start offsets (from the start of QuickeningInfo) in previous
49 //                                 table for each dex file
50 
51 class VdexFile {
52  public:
53   struct Header {
54    public:
55     Header(uint32_t number_of_dex_files_,
56            uint32_t dex_size,
57            uint32_t verifier_deps_size,
58            uint32_t quickening_info_size);
59 
GetMagicHeader60     const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
GetVersionHeader61     const char* GetVersion() const { return reinterpret_cast<const char*>(version_); }
62     bool IsMagicValid() const;
63     bool IsVersionValid() const;
IsValidHeader64     bool IsValid() const { return IsMagicValid() && IsVersionValid(); }
65 
GetDexSizeHeader66     uint32_t GetDexSize() const { return dex_size_; }
GetVerifierDepsSizeHeader67     uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
GetQuickeningInfoSizeHeader68     uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; }
GetNumberOfDexFilesHeader69     uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; }
70 
71     static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' };
72 
73    private:
74     static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
75     // Last update: Use set for unverified_classes_.
76     static constexpr uint8_t kVdexVersion[] = { '0', '1', '0', '\0' };
77 
78     uint8_t magic_[4];
79     uint8_t version_[4];
80     uint32_t number_of_dex_files_;
81     uint32_t dex_size_;
82     uint32_t verifier_deps_size_;
83     uint32_t quickening_info_size_;
84 
85     friend class VdexFile;
86   };
87 
88   typedef uint32_t VdexChecksum;
89 
90   // Returns nullptr if the vdex file cannot be opened or is not valid.
91   static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename,
92                                         bool writable,
93                                         bool low_4gb,
94                                         bool unquicken,
95                                         std::string* error_msg);
96 
97   // Returns nullptr if the vdex file cannot be opened or is not valid.
98   static std::unique_ptr<VdexFile> Open(int file_fd,
99                                         size_t vdex_length,
100                                         const std::string& vdex_filename,
101                                         bool writable,
102                                         bool low_4gb,
103                                         bool unquicken,
104                                         std::string* error_msg);
105 
Begin()106   const uint8_t* Begin() const { return mmap_->Begin(); }
End()107   const uint8_t* End() const { return mmap_->End(); }
Size()108   size_t Size() const { return mmap_->Size(); }
109 
GetHeader()110   const Header& GetHeader() const {
111     return *reinterpret_cast<const Header*>(Begin());
112   }
113 
GetVerifierDepsData()114   ArrayRef<const uint8_t> GetVerifierDepsData() const {
115     return ArrayRef<const uint8_t>(
116         DexBegin() + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize());
117   }
118 
GetQuickeningInfo()119   ArrayRef<const uint8_t> GetQuickeningInfo() const {
120     return ArrayRef<const uint8_t>(
121         GetVerifierDepsData().data() + GetHeader().GetVerifierDepsSize(),
122         GetHeader().GetQuickeningInfoSize());
123   }
124 
IsValid()125   bool IsValid() const {
126     return mmap_->Size() >= sizeof(Header) && GetHeader().IsValid();
127   }
128 
129   // This method is for iterating over the dex files in the vdex. If `cursor` is null,
130   // the first dex file is returned. If `cursor` is not null, it must point to a dex
131   // file and this method returns the next dex file if there is one, or null if there
132   // is none.
133   const uint8_t* GetNextDexFileData(const uint8_t* cursor) const;
134 
135   // Get the location checksum of the dex file number `dex_file_index`.
GetLocationChecksum(uint32_t dex_file_index)136   uint32_t GetLocationChecksum(uint32_t dex_file_index) const {
137     DCHECK_LT(dex_file_index, GetHeader().GetNumberOfDexFiles());
138     return reinterpret_cast<const uint32_t*>(Begin() + sizeof(Header))[dex_file_index];
139   }
140 
141   // Open all the dex files contained in this vdex file.
142   bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
143                        std::string* error_msg);
144 
145   // In-place unquicken the given `dex_files` based on `quickening_info`.
146   static void Unquicken(const std::vector<const DexFile*>& dex_files,
147                         const ArrayRef<const uint8_t>& quickening_info);
148 
149   // Fully unquicken `target_dex_file` based on quickening info stored
150   // in this vdex file for `original_dex_file`.
151   void FullyUnquickenDexFile(const DexFile& target_dex_file,
152                              const DexFile& original_dex_file) const;
153 
154   // Return the quickening info of the given code item.
155   const uint8_t* GetQuickenedInfoOf(const DexFile& dex_file, uint32_t code_item_offset) const;
156 
157  private:
VdexFile(MemMap * mmap)158   explicit VdexFile(MemMap* mmap) : mmap_(mmap) {}
159 
HasDexSection()160   bool HasDexSection() const {
161     return GetHeader().GetDexSize() != 0;
162   }
163 
DexBegin()164   const uint8_t* DexBegin() const {
165     return Begin() + sizeof(Header) + GetSizeOfChecksumsSection();
166   }
167 
DexEnd()168   const uint8_t* DexEnd() const {
169     return DexBegin() + GetHeader().GetDexSize();
170   }
171 
GetSizeOfChecksumsSection()172   size_t GetSizeOfChecksumsSection() const {
173     return sizeof(VdexChecksum) * GetHeader().GetNumberOfDexFiles();
174   }
175 
176   uint32_t GetDexFileIndex(const DexFile& dex_file) const;
177 
178   std::unique_ptr<MemMap> mmap_;
179 
180   DISALLOW_COPY_AND_ASSIGN(VdexFile);
181 };
182 
183 }  // namespace art
184 
185 #endif  // ART_RUNTIME_VDEX_FILE_H_
186