blob: eb8b81742bf4e81687fc7531ec36041f92a2b84b [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 Sehr79e26072018-04-06 17:58:50 -070025#include "base/mem_map.h"
David Sehrc431b9d2018-03-02 12:01:51 -080026#include "base/os.h"
Nicolas Geoffray6df45112021-02-07 21:51:58 +000027#include "class_status.h"
Mathieu Chartier2daa1342018-02-20 16:19:28 -080028#include "dex/compact_offset_table.h"
David Brazdil35a3f6a2019-03-04 15:59:06 +000029#include "dex/dex_file.h"
Mathieu Chartier210531f2018-01-12 10:15:51 -080030#include "quicken_info.h"
Nicolas Geoffray6df45112021-02-07 21:51:58 +000031#include "handle.h"
David Brazdil7b49e6c2016-09-01 11:06:18 +010032
33namespace art {
34
David Brazdil35a3f6a2019-03-04 15:59:06 +000035class ClassLoaderContext;
Nicolas Geoffray6df45112021-02-07 21:51:58 +000036class Thread;
37
38namespace mirror {
39class Class;
40}
David Brazdil35a3f6a2019-03-04 15:59:06 +000041
42namespace verifier {
43class VerifierDeps;
44} // namespace verifier
David Sehrbeca4fe2017-03-30 17:50:24 -070045
David Brazdil7b49e6c2016-09-01 11:06:18 +010046// VDEX files contain extracted DEX files. The VdexFile class maps the file to
47// memory and provides tools for accessing its individual sections.
48//
Nicolas Geoffray07b62e32020-11-07 15:54:08 +000049// In the description below, D is the number of dex files.
50//
David Brazdil7b49e6c2016-09-01 11:06:18 +010051// File format:
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +000052// VdexFileHeader fixed-length header
53// VdexSectionHeader[kNumberOfSections]
54//
55// Checksum section
56// VdexChecksum[D]
David Brazdil7b49e6c2016-09-01 11:06:18 +010057//
Nicolas Geoffray3a293552018-03-02 10:52:16 +000058// Optionally:
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +000059// DexSection
60// DEX[0] array of the input DEX files
61// DEX[1]
62// ...
63// DEX[D-1]
Nicolas Geoffray3a293552018-03-02 10:52:16 +000064//
Nicolas Geoffrayb4c6acb2017-11-10 12:48:14 +000065// VerifierDeps
Nicolas Geoffray07b62e32020-11-07 15:54:08 +000066// 4-byte alignment
67// uint32[D] DexFileDeps offsets for each dex file
68// DexFileDeps[D][] verification dependencies
69// 4-byte alignment
70// uint32[class_def_size] TypeAssignability offsets (kNotVerifiedMarker for a class
71// that isn't verified)
72// uint32 Offset of end of AssignabilityType sets
73// uint8[] AssignabilityType sets
74// 4-byte alignment
75// uint32 Number of strings
76// uint32[] String data offsets for each string
77// uint8[] String data
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +000078
79
80enum VdexSection : uint32_t {
81 kChecksumSection = 0,
82 kDexFileSection = 1,
83 kVerifierDepsSection = 2,
Nicolas Geoffray0b943282021-04-16 09:16:00 +000084 kTypeLookupTableSection = 3,
85 kNumberOfSections = 4,
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +000086};
David Brazdil7b49e6c2016-09-01 11:06:18 +010087
88class VdexFile {
89 public:
David Brazdil35a3f6a2019-03-04 15:59:06 +000090 using VdexChecksum = uint32_t;
David Brazdil35a3f6a2019-03-04 15:59:06 +000091
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +000092 struct VdexSectionHeader {
93 VdexSection section_kind;
94 uint32_t section_offset;
95 uint32_t section_size;
96
97 VdexSectionHeader(VdexSection kind, uint32_t offset, uint32_t size)
98 : section_kind(kind), section_offset(offset), section_size(size) {}
99
100 VdexSectionHeader() {}
101 };
102
103 struct VdexFileHeader {
David Brazdil7b49e6c2016-09-01 11:06:18 +0100104 public:
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000105 explicit VdexFileHeader(bool has_dex_section);
David Brazdil7b49e6c2016-09-01 11:06:18 +0100106
Nicolas Geoffraye70dd562016-10-30 21:03:35 +0000107 const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000108 const char* GetVdexVersion() const {
109 return reinterpret_cast<const char*>(vdex_version_);
David Brazdil93592f52017-12-08 10:53:27 +0000110 }
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000111 uint32_t GetNumberOfSections() const {
112 return number_of_sections_;
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000113 }
114 bool IsMagicValid() const;
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000115 bool IsVdexVersionValid() const;
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000116 bool IsValid() const {
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000117 return IsMagicValid() && IsVdexVersionValid();
David Brazdil35a3f6a2019-03-04 15:59:06 +0000118 }
119
Nicolas Geoffray36930ec2017-05-09 13:23:34 +0100120 static constexpr uint8_t kVdexInvalidMagic[] = { 'w', 'd', 'e', 'x' };
121
David Brazdil7b49e6c2016-09-01 11:06:18 +0100122 private:
123 static constexpr uint8_t kVdexMagic[] = { 'v', 'd', 'e', 'x' };
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000124
125 // The format version of the verifier deps header and the verifier deps.
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000126 // Last update: Introduce vdex sections.
127 static constexpr uint8_t kVdexVersion[] = { '0', '2', '7', '\0' };
David Brazdil7b49e6c2016-09-01 11:06:18 +0100128
129 uint8_t magic_[4];
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000130 uint8_t vdex_version_[4];
131 uint32_t number_of_sections_;
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000132 };
133
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000134 const VdexSectionHeader& GetSectionHeaderAt(uint32_t index) const {
135 DCHECK_LT(index, GetVdexFileHeader().GetNumberOfSections());
136 return *reinterpret_cast<const VdexSectionHeader*>(
137 Begin() + sizeof(VdexFileHeader) + index * sizeof(VdexSectionHeader));
138 }
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000139
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000140 const VdexSectionHeader& GetSectionHeader(VdexSection kind) const {
141 return GetSectionHeaderAt(static_cast<uint32_t>(kind));
142 }
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000143
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000144 static size_t GetChecksumsOffset() {
145 return sizeof(VdexFileHeader) +
146 static_cast<size_t>(VdexSection::kNumberOfSections) * sizeof(VdexSectionHeader);
147 }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100148
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000149 size_t GetComputedFileSize() const {
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000150 const VdexFileHeader& header = GetVdexFileHeader();
151 uint32_t size = sizeof(VdexFileHeader) +
152 header.GetNumberOfSections() * sizeof(VdexSectionHeader);
153 for (uint32_t i = 0; i < header.GetNumberOfSections(); ++i) {
154 size = std::max(size,
155 GetSectionHeaderAt(i).section_offset + GetSectionHeaderAt(i).section_size);
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000156 }
157 return size;
158 }
159
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000160 bool IsDexSectionValid() const;
161
162 bool HasDexSection() const {
163 return GetSectionHeader(VdexSection::kDexFileSection).section_size != 0u;
164 }
165 uint32_t GetVerifierDepsSize() const {
166 return GetSectionHeader(VdexSection::kVerifierDepsSection).section_size;
167 }
168 uint32_t GetNumberOfDexFiles() const {
169 return GetSectionHeader(VdexSection::kChecksumSection).section_size / sizeof(VdexChecksum);
170 }
171
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000172 bool HasTypeLookupTableSection() const {
173 return GetVdexFileHeader().GetNumberOfSections() >= (kTypeLookupTableSection + 1);
174 }
175
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000176 const VdexChecksum* GetDexChecksumsArray() const {
177 return reinterpret_cast<const VdexChecksum*>(
178 Begin() + GetSectionHeader(VdexSection::kChecksumSection).section_offset);
179 }
180
181 VdexChecksum GetDexChecksumAt(size_t idx) const {
182 DCHECK_LT(idx, GetNumberOfDexFiles());
183 return GetDexChecksumsArray()[idx];
184 }
185
Nicolas Geoffraybaeaa9b2018-01-26 14:31:17 +0000186 // Note: The file is called "primary" to match the naming with profiles.
187 static const constexpr char* kVdexNameInDmFile = "primary.vdex";
188
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100189 explicit VdexFile(MemMap&& mmap) : mmap_(std::move(mmap)) {}
Anestis Bechtsoudisa1f56a82017-10-08 23:37:10 +0300190
Richard Uhlerb8ab63a2017-01-31 11:27:37 +0000191 // Returns nullptr if the vdex file cannot be opened or is not valid.
David Srbeckyec2cdf42017-12-08 16:21:25 +0000192 // The mmap_* parameters can be left empty (nullptr/0/false) to allocate at random address.
193 static std::unique_ptr<VdexFile> OpenAtAddress(uint8_t* mmap_addr,
194 size_t mmap_size,
195 bool mmap_reuse,
196 const std::string& vdex_filename,
197 bool writable,
198 bool low_4gb,
199 bool unquicken,
200 std::string* error_msg);
201
202 // Returns nullptr if the vdex file cannot be opened or is not valid.
203 // The mmap_* parameters can be left empty (nullptr/0/false) to allocate at random address.
204 static std::unique_ptr<VdexFile> OpenAtAddress(uint8_t* mmap_addr,
205 size_t mmap_size,
206 bool mmap_reuse,
207 int file_fd,
208 size_t vdex_length,
209 const std::string& vdex_filename,
210 bool writable,
211 bool low_4gb,
212 bool unquicken,
213 std::string* error_msg);
214
215 // Returns nullptr if the vdex file cannot be opened or is not valid.
Richard Uhlerb8ab63a2017-01-31 11:27:37 +0000216 static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename,
217 bool writable,
218 bool low_4gb,
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100219 bool unquicken,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000220 std::string* error_msg) {
221 return OpenAtAddress(nullptr,
222 0,
223 false,
224 vdex_filename,
225 writable,
226 low_4gb,
227 unquicken,
228 error_msg);
229 }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100230
Richard Uhlerb8ab63a2017-01-31 11:27:37 +0000231 // Returns nullptr if the vdex file cannot be opened or is not valid.
232 static std::unique_ptr<VdexFile> Open(int file_fd,
233 size_t vdex_length,
234 const std::string& vdex_filename,
235 bool writable,
236 bool low_4gb,
Nicolas Geoffray4e868fa2017-04-21 17:16:44 +0100237 bool unquicken,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000238 std::string* error_msg) {
239 return OpenAtAddress(nullptr,
240 0,
241 false,
242 file_fd,
243 vdex_length,
244 vdex_filename,
245 writable,
246 low_4gb,
247 unquicken,
248 error_msg);
249 }
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000250
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100251 const uint8_t* Begin() const { return mmap_.Begin(); }
252 const uint8_t* End() const { return mmap_.End(); }
253 size_t Size() const { return mmap_.Size(); }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100254
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000255 const VdexFileHeader& GetVdexFileHeader() const {
256 return *reinterpret_cast<const VdexFileHeader*>(Begin());
Nicolas Geoffraye70dd562016-10-30 21:03:35 +0000257 }
258
259 ArrayRef<const uint8_t> GetVerifierDepsData() const {
260 return ArrayRef<const uint8_t>(
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000261 Begin() + GetSectionHeader(VdexSection::kVerifierDepsSection).section_offset,
262 GetSectionHeader(VdexSection::kVerifierDepsSection).section_size);
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000263 }
264
265 bool IsValid() const {
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000266 return mmap_.Size() >= sizeof(VdexFileHeader) && GetVdexFileHeader().IsValid();
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000267 }
268
269 // This method is for iterating over the dex files in the vdex. If `cursor` is null,
270 // the first dex file is returned. If `cursor` is not null, it must point to a dex
271 // file and this method returns the next dex file if there is one, or null if there
272 // is none.
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000273 const uint8_t* GetNextDexFileData(const uint8_t* cursor, uint32_t dex_file_index) const;
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000274
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000275 const uint8_t* GetNextTypeLookupTableData(const uint8_t* cursor, uint32_t dex_file_index) const;
276
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000277 // Get the location checksum of the dex file number `dex_file_index`.
278 uint32_t GetLocationChecksum(uint32_t dex_file_index) const {
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000279 DCHECK_LT(dex_file_index, GetNumberOfDexFiles());
280 return GetDexChecksumAt(dex_file_index);
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000281 }
282
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100283 // Open all the dex files contained in this vdex file.
David Sehrbeca4fe2017-03-30 17:50:24 -0700284 bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
Alex Lightabd8f052019-12-06 10:49:17 -0800285 std::string* error_msg) const;
David Sehrbeca4fe2017-03-30 17:50:24 -0700286
David Brazdil35a3f6a2019-03-04 15:59:06 +0000287 // Writes a vdex into `path` and returns true on success.
288 // The vdex will not contain a dex section but will store checksums of `dex_files`,
289 // encoded `verifier_deps`, as well as the current boot class path cheksum and
290 // encoded `class_loader_context`.
291 static bool WriteToDisk(const std::string& path,
292 const std::vector<const DexFile*>& dex_files,
293 const verifier::VerifierDeps& verifier_deps,
David Brazdil35a3f6a2019-03-04 15:59:06 +0000294 std::string* error_msg);
295
David Brazdil7126c5b2019-03-05 00:02:51 +0000296 // Returns true if the dex file checksums stored in the vdex header match
297 // the checksums in `dex_headers`. Both the number of dex files and their
298 // order must match too.
299 bool MatchesDexFileChecksums(const std::vector<const DexFile::Header*>& dex_headers) const;
300
Nicolas Geoffray6df45112021-02-07 21:51:58 +0000301 ClassStatus ComputeClassStatus(Thread* self, Handle<mirror::Class> cls) const
302 REQUIRES_SHARED(Locks::mutator_lock_);
303
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000304 // Return the name of the underlying `MemMap` of the vdex file, typically the
305 // location on disk of the vdex file.
306 const std::string& GetName() const {
307 return mmap_.GetName();
308 }
309
David Brazdil7b49e6c2016-09-01 11:06:18 +0100310 private:
Mathieu Chartier210531f2018-01-12 10:15:51 -0800311 bool ContainsDexFile(const DexFile& dex_file) const;
312
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000313 const uint8_t* DexBegin() const {
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000314 DCHECK(HasDexSection());
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000315 return Begin() + GetSectionHeader(VdexSection::kDexFileSection).section_offset;
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000316 }
317
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000318 const uint8_t* TypeLookupTableDataBegin() const {
319 DCHECK(HasTypeLookupTableSection());
320 return Begin() + GetSectionHeader(VdexSection::kTypeLookupTableSection).section_offset;
321 }
322
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000323 MemMap mmap_;
David Brazdil7b49e6c2016-09-01 11:06:18 +0100324
325 DISALLOW_COPY_AND_ASSIGN(VdexFile);
326};
327
328} // namespace art
329
330#endif // ART_RUNTIME_VDEX_FILE_H_