blob: 36fe09c5a0bce4d08ff1fd1b95de109e70204b06 [file] [log] [blame]
David Brazdil7b49e6c2016-09-01 11:06:18 +01001/*
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
Nicolas Geoffraye70dd562016-10-30 21:03:35 +000023#include "base/array_ref.h"
David Brazdil7b49e6c2016-09-01 11:06:18 +010024#include "base/macros.h"
David Brazdil7b49e6c2016-09-01 11:06:18 +010025#include "mem_map.h"
26#include "os.h"
Mathieu Chartier210531f2018-01-12 10:15:51 -080027#include "quicken_info.h"
David Brazdil7b49e6c2016-09-01 11:06:18 +010028
29namespace art {
30
David Sehrbeca4fe2017-03-30 17:50:24 -070031class DexFile;
32
David Brazdil7b49e6c2016-09-01 11:06:18 +010033// VDEX files contain extracted DEX files. The VdexFile class maps the file to
34// memory and provides tools for accessing its individual sections.
35//
36// File format:
37// VdexFile::Header fixed-length header
38//
Mathieu Chartier210531f2018-01-12 10:15:51 -080039// quicken_table_off[0] offset into QuickeningInfo section for offset table for DEX[0].
40// DEX[0] array of the input DEX files, the bytecode may have been quickened.
41// quicken_table_off[1]
42// DEX[1]
David Brazdil7b49e6c2016-09-01 11:06:18 +010043// ...
44// DEX[D]
Nicolas Geoffrayb4c6acb2017-11-10 12:48:14 +000045// VerifierDeps
46// uint8[D][] verification dependencies
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +010047// QuickeningInfo
Nicolas Geoffrayb4c6acb2017-11-10 12:48:14 +000048// uint8[D][] quickening data
Mathieu Chartier210531f2018-01-12 10:15:51 -080049// uint32[D][] quickening data offset tables
David Brazdil7b49e6c2016-09-01 11:06:18 +010050
51class VdexFile {
52 public:
53 struct Header {
54 public:
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +000055 Header(uint32_t number_of_dex_files_,
56 uint32_t dex_size,
57 uint32_t verifier_deps_size,
58 uint32_t quickening_info_size);
David Brazdil7b49e6c2016-09-01 11:06:18 +010059
Nicolas Geoffraye70dd562016-10-30 21:03:35 +000060 const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
61 const char* GetVersion() const { return reinterpret_cast<const char*>(version_); }
David Brazdil7b49e6c2016-09-01 11:06:18 +010062 bool IsMagicValid() const;
63 bool IsVersionValid() const;
Nicolas Geoffraye70dd562016-10-30 21:03:35 +000064 bool IsValid() const { return IsMagicValid() && IsVersionValid(); }
David Brazdil7b49e6c2016-09-01 11:06:18 +010065
David Brazdil5d5a36b2016-09-14 15:34:10 +010066 uint32_t GetDexSize() const { return dex_size_; }
67 uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
Nicolas Geoffray4acefd32016-10-24 13:14:58 +010068 uint32_t GetQuickeningInfoSize() const { return quickening_info_size_; }
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +000069 uint32_t GetNumberOfDexFiles() const { return number_of_dex_files_; }
David Brazdil5d5a36b2016-09-14 15:34:10 +010070
David Brazdil93592f52017-12-08 10:53:27 +000071 size_t GetComputedFileSize() const {
72 return sizeof(Header) +
73 GetSizeOfChecksumsSection() +
74 GetDexSize() +
75 GetVerifierDepsSize() +
76 GetQuickeningInfoSize();
77 }
78
79 size_t GetSizeOfChecksumsSection() const {
80 return sizeof(VdexChecksum) * GetNumberOfDexFiles();
81 }
82
Nicolas Geoffray36930ec2017-05-09 13:23:34 +010083 static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' };
84
David Brazdil7b49e6c2016-09-01 11:06:18 +010085 private:
86 static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
Mathieu Chartier8740c662018-01-11 14:50:02 -080087 // Last update: Use efficient encoding for compact dex code item fields
88 static constexpr uint8_t kVdexVersion[] = { '0', '1', '5', '\0' };
David Brazdil7b49e6c2016-09-01 11:06:18 +010089
90 uint8_t magic_[4];
91 uint8_t version_[4];
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +000092 uint32_t number_of_dex_files_;
David Brazdil5d5a36b2016-09-14 15:34:10 +010093 uint32_t dex_size_;
94 uint32_t verifier_deps_size_;
Nicolas Geoffray4acefd32016-10-24 13:14:58 +010095 uint32_t quickening_info_size_;
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +010096
97 friend class VdexFile;
David Brazdil7b49e6c2016-09-01 11:06:18 +010098 };
99
Nicolas Geoffraybaeaa9b2018-01-26 14:31:17 +0000100 // Note: The file is called "primary" to match the naming with profiles.
101 static const constexpr char* kVdexNameInDmFile = "primary.vdex";
102
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000103 typedef uint32_t VdexChecksum;
Mathieu Chartier210531f2018-01-12 10:15:51 -0800104 using QuickeningTableOffsetType = uint32_t;
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000105
Anestis Bechtsoudisa1f56a82017-10-08 23:37:10 +0300106 explicit VdexFile(MemMap* mmap) : mmap_(mmap) {}
107
Richard Uhlerb8ab63a2017-01-31 11:27:37 +0000108 // Returns nullptr if the vdex file cannot be opened or is not valid.
David Srbeckyec2cdf42017-12-08 16:21:25 +0000109 // The mmap_* parameters can be left empty (nullptr/0/false) to allocate at random address.
110 static std::unique_ptr<VdexFile> OpenAtAddress(uint8_t* mmap_addr,
111 size_t mmap_size,
112 bool mmap_reuse,
113 const std::string& vdex_filename,
114 bool writable,
115 bool low_4gb,
116 bool unquicken,
117 std::string* error_msg);
118
119 // Returns nullptr if the vdex file cannot be opened or is not valid.
120 // The mmap_* parameters can be left empty (nullptr/0/false) to allocate at random address.
121 static std::unique_ptr<VdexFile> OpenAtAddress(uint8_t* mmap_addr,
122 size_t mmap_size,
123 bool mmap_reuse,
124 int file_fd,
125 size_t vdex_length,
126 const std::string& vdex_filename,
127 bool writable,
128 bool low_4gb,
129 bool unquicken,
130 std::string* error_msg);
131
132 // Returns nullptr if the vdex file cannot be opened or is not valid.
Richard Uhlerb8ab63a2017-01-31 11:27:37 +0000133 static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename,
134 bool writable,
135 bool low_4gb,
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100136 bool unquicken,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000137 std::string* error_msg) {
138 return OpenAtAddress(nullptr,
139 0,
140 false,
141 vdex_filename,
142 writable,
143 low_4gb,
144 unquicken,
145 error_msg);
146 }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100147
Richard Uhlerb8ab63a2017-01-31 11:27:37 +0000148 // Returns nullptr if the vdex file cannot be opened or is not valid.
149 static std::unique_ptr<VdexFile> Open(int file_fd,
150 size_t vdex_length,
151 const std::string& vdex_filename,
152 bool writable,
153 bool low_4gb,
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100154 bool unquicken,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000155 std::string* error_msg) {
156 return OpenAtAddress(nullptr,
157 0,
158 false,
159 file_fd,
160 vdex_length,
161 vdex_filename,
162 writable,
163 low_4gb,
164 unquicken,
165 error_msg);
166 }
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000167
David Brazdil7b49e6c2016-09-01 11:06:18 +0100168 const uint8_t* Begin() const { return mmap_->Begin(); }
169 const uint8_t* End() const { return mmap_->End(); }
170 size_t Size() const { return mmap_->Size(); }
171
Nicolas Geoffraye70dd562016-10-30 21:03:35 +0000172 const Header& GetHeader() const {
173 return *reinterpret_cast<const Header*>(Begin());
174 }
175
176 ArrayRef<const uint8_t> GetVerifierDepsData() const {
177 return ArrayRef<const uint8_t>(
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000178 DexBegin() + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize());
Nicolas Geoffraye70dd562016-10-30 21:03:35 +0000179 }
180
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000181 ArrayRef<const uint8_t> GetQuickeningInfo() const {
182 return ArrayRef<const uint8_t>(
183 GetVerifierDepsData().data() + GetHeader().GetVerifierDepsSize(),
184 GetHeader().GetQuickeningInfoSize());
185 }
186
187 bool IsValid() const {
188 return mmap_->Size() >= sizeof(Header) && GetHeader().IsValid();
189 }
190
191 // This method is for iterating over the dex files in the vdex. If `cursor` is null,
192 // the first dex file is returned. If `cursor` is not null, it must point to a dex
193 // file and this method returns the next dex file if there is one, or null if there
194 // is none.
195 const uint8_t* GetNextDexFileData(const uint8_t* cursor) const;
196
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000197 // Get the location checksum of the dex file number `dex_file_index`.
198 uint32_t GetLocationChecksum(uint32_t dex_file_index) const {
199 DCHECK_LT(dex_file_index, GetHeader().GetNumberOfDexFiles());
200 return reinterpret_cast<const uint32_t*>(Begin() + sizeof(Header))[dex_file_index];
201 }
202
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100203 // Open all the dex files contained in this vdex file.
David Sehrbeca4fe2017-03-30 17:50:24 -0700204 bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
205 std::string* error_msg);
206
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100207 // In-place unquicken the given `dex_files` based on `quickening_info`.
Anestis Bechtsoudisa1f56a82017-10-08 23:37:10 +0300208 // `decompile_return_instruction` controls if RETURN_VOID_BARRIER instructions are
209 // decompiled to RETURN_VOID instructions using the slower ClassDataItemIterator
210 // instead of the faster QuickeningInfoIterator.
Mathieu Chartier210531f2018-01-12 10:15:51 -0800211 // Always unquickens using the vdex dex files as the source for quicken tables.
212 void Unquicken(const std::vector<const DexFile*>& target_dex_files,
213 bool decompile_return_instruction) const;
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100214
Nicolas Geoffrayb4c6acb2017-11-10 12:48:14 +0000215 // Fully unquicken `target_dex_file` based on `quickening_info`.
Mathieu Chartier210531f2018-01-12 10:15:51 -0800216 void UnquickenDexFile(const DexFile& target_dex_file,
217 const DexFile& source_dex_file,
218 bool decompile_return_instruction) const;
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100219
Mathieu Chartier210531f2018-01-12 10:15:51 -0800220 // Return the quickening info of a given method index (or null if it's empty).
221 ArrayRef<const uint8_t> GetQuickenedInfoOf(const DexFile& dex_file,
222 uint32_t dex_method_idx) const;
Nicolas Geoffrayb4c6acb2017-11-10 12:48:14 +0000223
David Brazdil7b49e6c2016-09-01 11:06:18 +0100224 private:
Mathieu Chartier210531f2018-01-12 10:15:51 -0800225 uint32_t GetQuickeningInfoTableOffset(const uint8_t* source_dex_begin) const;
226
227 // Source dex must be the in the vdex file.
228 void UnquickenDexFile(const DexFile& target_dex_file,
229 const uint8_t* source_dex_begin,
230 bool decompile_return_instruction) const;
231
232 QuickenInfoOffsetTableAccessor GetQuickenInfoOffsetTable(
233 const DexFile& dex_file,
234 const ArrayRef<const uint8_t>& quickening_info) const;
235
236 QuickenInfoOffsetTableAccessor GetQuickenInfoOffsetTable(
237 const uint8_t* source_dex_begin,
238 uint32_t num_method_ids,
239 const ArrayRef<const uint8_t>& quickening_info) const;
240
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000241 bool HasDexSection() const {
242 return GetHeader().GetDexSize() != 0;
243 }
244
Mathieu Chartier210531f2018-01-12 10:15:51 -0800245 bool ContainsDexFile(const DexFile& dex_file) const;
246
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000247 const uint8_t* DexBegin() const {
David Brazdil93592f52017-12-08 10:53:27 +0000248 return Begin() + sizeof(Header) + GetHeader().GetSizeOfChecksumsSection();
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000249 }
250
251 const uint8_t* DexEnd() const {
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000252 return DexBegin() + GetHeader().GetDexSize();
253 }
254
David Brazdil7b49e6c2016-09-01 11:06:18 +0100255 std::unique_ptr<MemMap> mmap_;
256
257 DISALLOW_COPY_AND_ASSIGN(VdexFile);
258};
259
260} // namespace art
261
262#endif // ART_RUNTIME_VDEX_FILE_H_