blob: 3ccbfa556719ab1f3817705509d373618766ad48 [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 HasDexSection() const {
161 return GetSectionHeader(VdexSection::kDexFileSection).section_size != 0u;
162 }
163 uint32_t GetVerifierDepsSize() const {
164 return GetSectionHeader(VdexSection::kVerifierDepsSection).section_size;
165 }
166 uint32_t GetNumberOfDexFiles() const {
167 return GetSectionHeader(VdexSection::kChecksumSection).section_size / sizeof(VdexChecksum);
168 }
169
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000170 bool HasTypeLookupTableSection() const {
171 return GetVdexFileHeader().GetNumberOfSections() >= (kTypeLookupTableSection + 1);
172 }
173
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000174 const VdexChecksum* GetDexChecksumsArray() const {
175 return reinterpret_cast<const VdexChecksum*>(
176 Begin() + GetSectionHeader(VdexSection::kChecksumSection).section_offset);
177 }
178
179 VdexChecksum GetDexChecksumAt(size_t idx) const {
180 DCHECK_LT(idx, GetNumberOfDexFiles());
181 return GetDexChecksumsArray()[idx];
182 }
183
Nicolas Geoffraybaeaa9b2018-01-26 14:31:17 +0000184 // Note: The file is called "primary" to match the naming with profiles.
185 static const constexpr char* kVdexNameInDmFile = "primary.vdex";
186
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100187 explicit VdexFile(MemMap&& mmap) : mmap_(std::move(mmap)) {}
Anestis Bechtsoudisa1f56a82017-10-08 23:37:10 +0300188
Richard Uhlerb8ab63a2017-01-31 11:27:37 +0000189 // Returns nullptr if the vdex file cannot be opened or is not valid.
David Srbeckyec2cdf42017-12-08 16:21:25 +0000190 // The mmap_* parameters can be left empty (nullptr/0/false) to allocate at random address.
191 static std::unique_ptr<VdexFile> OpenAtAddress(uint8_t* mmap_addr,
192 size_t mmap_size,
193 bool mmap_reuse,
194 const std::string& vdex_filename,
195 bool writable,
196 bool low_4gb,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000197 std::string* error_msg);
198
199 // Returns nullptr if the vdex file cannot be opened or is not valid.
200 // The mmap_* parameters can be left empty (nullptr/0/false) to allocate at random address.
201 static std::unique_ptr<VdexFile> OpenAtAddress(uint8_t* mmap_addr,
202 size_t mmap_size,
203 bool mmap_reuse,
204 int file_fd,
205 size_t vdex_length,
206 const std::string& vdex_filename,
207 bool writable,
208 bool low_4gb,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000209 std::string* error_msg);
210
211 // Returns nullptr if the vdex file cannot be opened or is not valid.
Richard Uhlerb8ab63a2017-01-31 11:27:37 +0000212 static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename,
213 bool writable,
214 bool low_4gb,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000215 std::string* error_msg) {
216 return OpenAtAddress(nullptr,
217 0,
218 false,
219 vdex_filename,
220 writable,
221 low_4gb,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000222 error_msg);
223 }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100224
Richard Uhlerb8ab63a2017-01-31 11:27:37 +0000225 // Returns nullptr if the vdex file cannot be opened or is not valid.
226 static std::unique_ptr<VdexFile> Open(int file_fd,
227 size_t vdex_length,
228 const std::string& vdex_filename,
229 bool writable,
230 bool low_4gb,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000231 std::string* error_msg) {
232 return OpenAtAddress(nullptr,
233 0,
234 false,
235 file_fd,
236 vdex_length,
237 vdex_filename,
238 writable,
239 low_4gb,
David Srbeckyec2cdf42017-12-08 16:21:25 +0000240 error_msg);
241 }
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000242
Nicolas Geoffray327cfcf2021-10-12 14:13:25 +0100243 static std::unique_ptr<VdexFile> OpenFromDm(const std::string& filename,
244 const ZipArchive& archive);
245
Vladimir Markoc34bebf2018-08-16 16:12:49 +0100246 const uint8_t* Begin() const { return mmap_.Begin(); }
247 const uint8_t* End() const { return mmap_.End(); }
248 size_t Size() const { return mmap_.Size(); }
Nicolas Geoffraya74a7072021-09-09 17:06:46 +0100249 bool Contains(const uint8_t* pointer) const {
250 return pointer >= Begin() && pointer < End();
251 }
David Brazdil7b49e6c2016-09-01 11:06:18 +0100252
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000253 const VdexFileHeader& GetVdexFileHeader() const {
254 return *reinterpret_cast<const VdexFileHeader*>(Begin());
Nicolas Geoffraye70dd562016-10-30 21:03:35 +0000255 }
256
257 ArrayRef<const uint8_t> GetVerifierDepsData() const {
258 return ArrayRef<const uint8_t>(
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000259 Begin() + GetSectionHeader(VdexSection::kVerifierDepsSection).section_offset,
260 GetSectionHeader(VdexSection::kVerifierDepsSection).section_size);
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000261 }
262
263 bool IsValid() const {
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000264 return mmap_.Size() >= sizeof(VdexFileHeader) && GetVdexFileHeader().IsValid();
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000265 }
266
267 // This method is for iterating over the dex files in the vdex. If `cursor` is null,
268 // the first dex file is returned. If `cursor` is not null, it must point to a dex
269 // file and this method returns the next dex file if there is one, or null if there
270 // is none.
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000271 const uint8_t* GetNextDexFileData(const uint8_t* cursor, uint32_t dex_file_index) const;
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000272
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000273 const uint8_t* GetNextTypeLookupTableData(const uint8_t* cursor, uint32_t dex_file_index) const;
274
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000275 // Get the location checksum of the dex file number `dex_file_index`.
276 uint32_t GetLocationChecksum(uint32_t dex_file_index) const {
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000277 DCHECK_LT(dex_file_index, GetNumberOfDexFiles());
278 return GetDexChecksumAt(dex_file_index);
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000279 }
280
Nicolas Geoffrayb02ba932017-07-13 15:53:54 +0100281 // Open all the dex files contained in this vdex file.
David Sehrbeca4fe2017-03-30 17:50:24 -0700282 bool OpenAllDexFiles(std::vector<std::unique_ptr<const DexFile>>* dex_files,
Alex Lightabd8f052019-12-06 10:49:17 -0800283 std::string* error_msg) const;
David Sehrbeca4fe2017-03-30 17:50:24 -0700284
David Brazdil35a3f6a2019-03-04 15:59:06 +0000285 // Writes a vdex into `path` and returns true on success.
286 // The vdex will not contain a dex section but will store checksums of `dex_files`,
287 // encoded `verifier_deps`, as well as the current boot class path cheksum and
288 // encoded `class_loader_context`.
289 static bool WriteToDisk(const std::string& path,
290 const std::vector<const DexFile*>& dex_files,
291 const verifier::VerifierDeps& verifier_deps,
David Brazdil35a3f6a2019-03-04 15:59:06 +0000292 std::string* error_msg);
293
David Brazdil7126c5b2019-03-05 00:02:51 +0000294 // Returns true if the dex file checksums stored in the vdex header match
295 // the checksums in `dex_headers`. Both the number of dex files and their
296 // order must match too.
297 bool MatchesDexFileChecksums(const std::vector<const DexFile::Header*>& dex_headers) const;
298
Nicolas Geoffray6df45112021-02-07 21:51:58 +0000299 ClassStatus ComputeClassStatus(Thread* self, Handle<mirror::Class> cls) const
300 REQUIRES_SHARED(Locks::mutator_lock_);
301
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000302 // Return the name of the underlying `MemMap` of the vdex file, typically the
303 // location on disk of the vdex file.
304 const std::string& GetName() const {
305 return mmap_.GetName();
306 }
307
David Brazdil7b49e6c2016-09-01 11:06:18 +0100308 private:
Mathieu Chartier210531f2018-01-12 10:15:51 -0800309 bool ContainsDexFile(const DexFile& dex_file) const;
310
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000311 const uint8_t* DexBegin() const {
Nicolas Geoffray3a293552018-03-02 10:52:16 +0000312 DCHECK(HasDexSection());
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000313 return Begin() + GetSectionHeader(VdexSection::kDexFileSection).section_offset;
Nicolas Geoffrayb0bbe8e2016-11-19 10:42:37 +0000314 }
315
Nicolas Geoffray0b943282021-04-16 09:16:00 +0000316 const uint8_t* TypeLookupTableDataBegin() const {
317 DCHECK(HasTypeLookupTableSection());
318 return Begin() + GetSectionHeader(VdexSection::kTypeLookupTableSection).section_offset;
319 }
320
Nicolas Geoffraya129d8a2021-03-18 22:23:04 +0000321 MemMap mmap_;
David Brazdil7b49e6c2016-09-01 11:06:18 +0100322
323 DISALLOW_COPY_AND_ASSIGN(VdexFile);
324};
325
326} // namespace art
327
328#endif // ART_RUNTIME_VDEX_FILE_H_