blob: 81cd23198fb2600a765a725c00577e8b51f331ef [file] [log] [blame]
Richard Uhler66d874d2015-01-15 09:37:19 -08001/*
2 * Copyright (C) 2014 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_OAT_FILE_ASSISTANT_H_
18#define ART_RUNTIME_OAT_FILE_ASSISTANT_H_
19
20#include <cstdint>
21#include <memory>
Jiakai Zhang78d86b52022-05-26 17:24:17 +010022#include <optional>
Narayan Kamath8943c1d2016-05-02 13:14:48 +010023#include <sstream>
Richard Uhler66d874d2015-01-15 09:37:19 -080024#include <string>
Jiakai Zhang7a5a95f2022-08-07 01:12:24 +010025#include <variant>
Richard Uhler66d874d2015-01-15 09:37:19 -080026
27#include "arch/instruction_set.h"
Jiakai Zhang78d86b52022-05-26 17:24:17 +010028#include "base/compiler_filter.h"
David Sehrc431b9d2018-03-02 12:01:51 -080029#include "base/os.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080030#include "base/scoped_flock.h"
31#include "base/unix_file/fd_file.h"
Calin Juravle44e5efa2017-09-12 00:54:26 -070032#include "class_loader_context.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080033#include "oat_file.h"
Jiakai Zhang7a5a95f2022-08-07 01:12:24 +010034#include "oat_file_assistant_context.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080035
36namespace art {
37
Mathieu Chartierfbc31082016-01-24 11:59:56 -080038namespace gc {
39namespace space {
40class ImageSpace;
41} // namespace space
42} // namespace gc
43
Richard Uhler66d874d2015-01-15 09:37:19 -080044// Class for assisting with oat file management.
45//
46// This class collects common utilities for determining the status of an oat
47// file on the device, updating the oat file, and loading the oat file.
48//
49// The oat file assistant is intended to be used with dex locations not on the
50// boot class path. See the IsInBootClassPath method for a way to check if the
51// dex location is in the boot class path.
Richard Uhler66d874d2015-01-15 09:37:19 -080052class OatFileAssistant {
53 public:
Richard Uhler95abd042015-03-24 09:51:28 -070054 enum DexOptNeeded {
Richard Uhler7225a8d2016-11-22 10:12:03 +000055 // No dexopt should (or can) be done to update the apk/jar.
Richard Uhler95abd042015-03-24 09:51:28 -070056 // Matches Java: dalvik.system.DexFile.NO_DEXOPT_NEEDED = 0
57 kNoDexOptNeeded = 0,
Richard Uhler66d874d2015-01-15 09:37:19 -080058
Richard Uhler7225a8d2016-11-22 10:12:03 +000059 // dex2oat should be run to update the apk/jar from scratch.
60 // Matches Java: dalvik.system.DexFile.DEX2OAT_FROM_SCRATCH = 1
61 kDex2OatFromScratch = 1,
Richard Uhler66d874d2015-01-15 09:37:19 -080062
Richard Uhler7225a8d2016-11-22 10:12:03 +000063 // dex2oat should be run to update the apk/jar because the existing code
64 // is out of date with respect to the boot image.
65 // Matches Java: dalvik.system.DexFile.DEX2OAT_FOR_BOOT_IMAGE
66 kDex2OatForBootImage = 2,
Richard Uhler95abd042015-03-24 09:51:28 -070067
Richard Uhler7225a8d2016-11-22 10:12:03 +000068 // dex2oat should be run to update the apk/jar because the existing code
69 // is out of date with respect to the target compiler filter.
70 // Matches Java: dalvik.system.DexFile.DEX2OAT_FOR_FILTER
71 kDex2OatForFilter = 3,
Richard Uhler95abd042015-03-24 09:51:28 -070072 };
73
74 enum OatStatus {
Richard Uhler03bc6592016-11-22 09:42:04 +000075 // kOatCannotOpen - The oat file cannot be opened, because it does not
76 // exist, is unreadable, or otherwise corrupted.
77 kOatCannotOpen,
Richard Uhler95abd042015-03-24 09:51:28 -070078
Richard Uhler03bc6592016-11-22 09:42:04 +000079 // kOatDexOutOfDate - The oat file is out of date with respect to the dex file.
80 kOatDexOutOfDate,
Richard Uhler95abd042015-03-24 09:51:28 -070081
Richard Uhler03bc6592016-11-22 09:42:04 +000082 // kOatBootImageOutOfDate - The oat file is up to date with respect to the
83 // dex file, but is out of date with respect to the boot image.
84 kOatBootImageOutOfDate,
85
Nicolas Geoffray525fa422021-04-19 07:50:35 +000086 // kOatContextOutOfDate - The context in the oat file is out of date with
87 // respect to the class loader context.
88 kOatContextOutOfDate,
89
Richard Uhler03bc6592016-11-22 09:42:04 +000090 // kOatUpToDate - The oat file is completely up to date with respect to
91 // the dex file and boot image.
Richard Uhler95abd042015-03-24 09:51:28 -070092 kOatUpToDate,
Richard Uhler66d874d2015-01-15 09:37:19 -080093 };
94
Jiakai Zhangdbfa7992022-06-24 23:14:24 +010095 // A bit field to represent the conditions where dexopt should be performed.
96 struct DexOptTrigger {
97 // Dexopt should be performed if the target compiler filter is better than the current compiler
98 // filter. See `CompilerFilter::IsBetter`.
99 bool targetFilterIsBetter : 1;
100 // Dexopt should be performed if the target compiler filter is the same as the current compiler
101 // filter.
102 bool targetFilterIsSame : 1;
103 // Dexopt should be performed if the target compiler filter is worse than the current compiler
104 // filter. See `CompilerFilter::IsBetter`.
105 bool targetFilterIsWorse : 1;
106 // Dexopt should be performed if the current oat file was compiled without a primary image,
107 // and the runtime is now running with a primary image loaded from disk.
108 bool primaryBootImageBecomesUsable : 1;
Jiakai Zhangc98ed722023-01-31 15:00:53 +0800109 // Dexopt should be performed if the APK is compressed and the current oat/vdex file doesn't
110 // contain dex code.
111 bool needExtraction : 1;
Jiakai Zhangdbfa7992022-06-24 23:14:24 +0100112 };
113
114 // Represents the location of the current oat file and/or vdex file.
115 enum Location {
116 // Does not exist, or an error occurs.
117 kLocationNoneOrError = 0,
118 // In the global "dalvik-cache" folder.
119 kLocationOat = 1,
120 // In the "oat" folder next to the dex file.
121 kLocationOdex = 2,
122 // In the DM file. This means the only usable file is the vdex file.
123 kLocationDm = 3,
124 };
125
126 // Represents the status of the current oat file and/or vdex file.
127 class DexOptStatus {
128 public:
129 Location GetLocation() { return location_; }
130 bool IsVdexUsable() { return location_ != kLocationNoneOrError; }
131
132 private:
133 Location location_ = kLocationNoneOrError;
134 friend class OatFileAssistant;
135 };
136
Richard Uhler66d874d2015-01-15 09:37:19 -0800137 // Constructs an OatFileAssistant object to assist the oat file
138 // corresponding to the given dex location with the target instruction set.
139 //
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700140 // The dex_location must not be null and should remain available and
Richard Uhler66d874d2015-01-15 09:37:19 -0800141 // unchanged for the duration of the lifetime of the OatFileAssistant object.
142 // Typically the dex_location is the absolute path to the original,
143 // un-optimized dex file.
144 //
Richard Uhler66d874d2015-01-15 09:37:19 -0800145 // Note: Currently the dex_location must have an extension.
146 // TODO: Relax this restriction?
147 //
148 // The isa should be either the 32 bit or 64 bit variant for the current
149 // device. For example, on an arm device, use arm or arm64. An oat file can
150 // be loaded executable only if the ISA matches the current runtime.
Andreas Gampe29d38e72016-03-23 15:31:51 +0000151 //
Jiakai Zhangb4593412022-10-28 11:50:26 +0100152 // context should be the class loader context to check against, or null to skip the check.
153 //
Andreas Gampe29d38e72016-03-23 15:31:51 +0000154 // load_executable should be true if the caller intends to try and load
155 // executable code for this dex location.
Nicolas Geoffray29742602017-12-14 10:09:03 +0000156 //
Orion Hodson094b1cf2021-06-08 09:28:28 +0100157 // only_load_trusted_executable should be true if the caller intends to have
158 // only oat files from trusted locations loaded executable. See IsTrustedLocation() for
159 // details on trusted locations.
Jiakai Zhang78d86b52022-05-26 17:24:17 +0100160 //
161 // runtime_options should be provided with all the required fields filled if the caller intends to
162 // use OatFileAssistant without a runtime.
Calin Juravleb077e152016-02-18 18:47:37 +0000163 OatFileAssistant(const char* dex_location,
Calin Juravleb077e152016-02-18 18:47:37 +0000164 const InstructionSet isa,
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000165 ClassLoaderContext* context,
Nicolas Geoffray29742602017-12-14 10:09:03 +0000166 bool load_executable,
Jiakai Zhang78d86b52022-05-26 17:24:17 +0100167 bool only_load_trusted_executable = false,
Jiakai Zhang7a5a95f2022-08-07 01:12:24 +0100168 OatFileAssistantContext* ofa_context = nullptr);
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700169
170 // Similar to this(const char*, const InstructionSet, bool), however, if a valid zip_fd is
171 // provided, vdex, oat, and zip files will be read from vdex_fd, oat_fd and zip_fd respectively.
172 // Otherwise, dex_location will be used to construct necessary filenames.
173 OatFileAssistant(const char* dex_location,
174 const InstructionSet isa,
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000175 ClassLoaderContext* context,
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700176 bool load_executable,
Orion Hodson094b1cf2021-06-08 09:28:28 +0100177 bool only_load_trusted_executable,
Jiakai Zhang7a5a95f2022-08-07 01:12:24 +0100178 OatFileAssistantContext* ofa_context,
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700179 int vdex_fd,
180 int oat_fd,
181 int zip_fd);
Richard Uhler66d874d2015-01-15 09:37:19 -0800182
Jiakai Zhang6c18fbd2022-06-24 19:01:45 +0100183 // A convenient factory function that accepts ISA, class loader context, and compiler filter in
Jiakai Zhang865006d2022-07-01 21:09:10 +0100184 // strings. Returns the created instance and ClassLoaderContext on success, or returns nullptr and
185 // outputs an error message if it fails to parse the input strings.
186 // The returned ClassLoaderContext must live at least as long as the OatFileAssistant.
187 static std::unique_ptr<OatFileAssistant> Create(
188 const std::string& filename,
189 const std::string& isa_str,
Jiakai Zhangb4593412022-10-28 11:50:26 +0100190 const std::optional<std::string>& context_str,
Jiakai Zhang865006d2022-07-01 21:09:10 +0100191 bool load_executable,
192 bool only_load_trusted_executable,
Jiakai Zhang7a5a95f2022-08-07 01:12:24 +0100193 OatFileAssistantContext* ofa_context,
Jiakai Zhang865006d2022-07-01 21:09:10 +0100194 /*out*/ std::unique_ptr<ClassLoaderContext>* context,
195 /*out*/ std::string* error_msg);
Jiakai Zhang6c18fbd2022-06-24 19:01:45 +0100196
Richard Uhler66d874d2015-01-15 09:37:19 -0800197 // Returns true if the dex location refers to an element of the boot class
198 // path.
199 bool IsInBootClassPath();
200
Richard Uhler95abd042015-03-24 09:51:28 -0700201 // Return what action needs to be taken to produce up-to-date code for this
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700202 // dex location. If "downgrade" is set to false, it verifies if the current
203 // compiler filter is at least as good as an oat file generated with the
204 // given compiler filter otherwise, if its set to true, it checks whether
205 // the oat file generated with the target filter will be downgraded as
206 // compared to the current state. For example, if the current compiler filter is
207 // quicken, and target filter is verify, it will recommend to dexopt, while
208 // if the target filter is speed profile, it will recommend to keep it in its
209 // current state.
210 // profile_changed should be true to indicate the profile has recently changed
211 // for this dex location.
212 // If the purpose of the dexopt is to downgrade the compiler filter,
213 // set downgrade to true.
Richard Uhler7225a8d2016-11-22 10:12:03 +0000214 // Returns a positive status code if the status refers to the oat file in
215 // the oat location. Returns a negative status code if the status refers to
216 // the oat file in the odex location.
Jiakai Zhangdbfa7992022-06-24 23:14:24 +0100217 //
218 // Deprecated. Use the other overload.
Shubham Ajmerae4e812a2017-05-25 20:09:58 -0700219 int GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
220 bool profile_changed = false,
Calin Juravle0a5cad32020-02-14 20:29:26 +0000221 bool downgrade = false);
Richard Uhler66d874d2015-01-15 09:37:19 -0800222
Jiakai Zhangdbfa7992022-06-24 23:14:24 +0100223 // Returns true if dexopt needs to be performed with respect to the given target compilation
224 // filter and dexopt trigger. Also returns the status of the current oat file and/or vdex file.
225 bool GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
226 const DexOptTrigger dexopt_trigger,
227 /*out*/ DexOptStatus* dexopt_status);
228
Richard Uhler01be6812016-05-17 10:34:52 -0700229 // Returns true if there is up-to-date code for this dex location,
230 // irrespective of the compiler filter of the up-to-date code.
231 bool IsUpToDate();
232
Richard Uhler66d874d2015-01-15 09:37:19 -0800233 // Returns an oat file that can be used for loading dex files.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700234 // Returns null if no suitable oat file was found.
Richard Uhler66d874d2015-01-15 09:37:19 -0800235 //
236 // After this call, no other methods of the OatFileAssistant should be
237 // called, because access to the loaded oat file has been taken away from
238 // the OatFileAssistant object.
239 std::unique_ptr<OatFile> GetBestOatFile();
240
Richard Uhler46cc64f2016-11-14 14:53:55 +0000241 // Returns a human readable description of the status of the code for the
242 // dex file. The returned description is for debugging purposes only.
243 std::string GetStatusDump();
244
Calin Juravle5f9a8012018-02-12 20:27:46 -0800245 // Computes the optimization status of the given dex file. The result is
246 // returned via the two output parameters.
Calin Juravle98071152021-01-27 18:41:58 -0800247 // - out_odex_location: the location of the (best) odex that will be used
248 // for loading. See GetBestInfo().
Calin Juravle5f9a8012018-02-12 20:27:46 -0800249 // - out_compilation_filter: the level of optimizations (compiler filter)
250 // - out_compilation_reason: the optimization reason. The reason might
251 // be "unknown" if the compiler artifacts were not annotated during optimizations.
Calin Juravle98071152021-01-27 18:41:58 -0800252 // - out_odex_status: a human readable refined status of the validity of the odex file.
Jiakai Zhang6c18fbd2022-06-24 19:01:45 +0100253 // Possible values are: "up-to-date", "apk-more-recent", and "io-error-no-oat".
Calin Juravle5f9a8012018-02-12 20:27:46 -0800254 //
255 // This method will try to mimic the runtime effect of loading the dex file.
256 // For example, if there is no usable oat file, the compiler filter will be set
257 // to "run-from-apk".
Calin Juravle98071152021-01-27 18:41:58 -0800258 void GetOptimizationStatus(std::string* out_odex_location,
259 std::string* out_compilation_filter,
260 std::string* out_compilation_reason,
261 std::string* out_odex_status);
262
Calin Juravle5f9a8012018-02-12 20:27:46 -0800263 static void GetOptimizationStatus(const std::string& filename,
264 InstructionSet isa,
265 std::string* out_compilation_filter,
Jiakai Zhang78d86b52022-05-26 17:24:17 +0100266 std::string* out_compilation_reason,
Jiakai Zhang7a5a95f2022-08-07 01:12:24 +0100267 OatFileAssistantContext* ofa_context = nullptr);
Calin Juravle5f9a8012018-02-12 20:27:46 -0800268
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800269 // Open and returns an image space associated with the oat file.
Andreas Gampea463b6a2016-08-12 21:53:32 -0700270 static std::unique_ptr<gc::space::ImageSpace> OpenImageSpace(const OatFile* oat_file);
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800271
Richard Uhler66d874d2015-01-15 09:37:19 -0800272 // Loads the dex files in the given oat file for the given dex location.
273 // The oat file should be up to date for the given dex location.
274 // This loads multiple dex files in the case of multidex.
275 // Returns an empty vector if no dex files for that location could be loaded
276 // from the oat file.
277 //
278 // The caller is responsible for freeing the dex_files returned, if any. The
279 // dex_files will only remain valid as long as the oat_file is valid.
280 static std::vector<std::unique_ptr<const DexFile>> LoadDexFiles(
281 const OatFile& oat_file, const char* dex_location);
282
Calin Juravle87e2cb62017-06-13 21:48:45 -0700283 // Same as `std::vector<std::unique_ptr<const DexFile>> LoadDexFiles(...)` with the difference:
284 // - puts the dex files in the given vector
285 // - returns whether or not all dex files were successfully opened
286 static bool LoadDexFiles(const OatFile& oat_file,
287 const std::string& dex_location,
288 std::vector<std::unique_ptr<const DexFile>>* out_dex_files);
289
Jiakai Zhangc372e792022-11-23 10:57:22 +0000290 // Returns whether this is an apk/zip wit a classes.dex entry, or nullopt if an error occurred.
291 std::optional<bool> HasDexFiles(std::string* error_msg);
Richard Uhler9b994ea2015-06-24 08:44:19 -0700292
Richard Uhler63434112015-03-16 14:32:16 -0700293 // If the dex file has been installed with a compiled oat file alongside
294 // it, the compiled oat file will have the extension .odex, and is referred
295 // to as the odex file. It is called odex for legacy reasons; the file is
296 // really an oat file. The odex file will often, but not always, have a
297 // patch delta of 0 and need to be relocated before use for the purposes of
298 // ASLR. The odex file is treated as if it were read-only.
Richard Uhler03bc6592016-11-22 09:42:04 +0000299 //
300 // Returns the status of the odex file for the dex location.
Richard Uhler95abd042015-03-24 09:51:28 -0700301 OatStatus OdexFileStatus();
Richard Uhler66d874d2015-01-15 09:37:19 -0800302
303 // When the dex files is compiled on the target device, the oat file is the
304 // result. The oat file will have been relocated to some
305 // (possibly-out-of-date) offset for ASLR.
Richard Uhler03bc6592016-11-22 09:42:04 +0000306 //
307 // Returns the status of the oat file for the dex location.
Richard Uhler95abd042015-03-24 09:51:28 -0700308 OatStatus OatFileStatus();
Richard Uhler66d874d2015-01-15 09:37:19 -0800309
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000310 OatStatus GetBestStatus() {
311 return GetBestInfo().Status();
312 }
313
Richard Uhler66d874d2015-01-15 09:37:19 -0800314 // Constructs the odex file name for the given dex location.
315 // Returns true on success, in which case odex_filename is set to the odex
316 // file name.
Richard Uhlere8e48ae2016-04-19 12:41:04 -0700317 // Returns false on error, in which case error_msg describes the error and
318 // odex_filename is not changed.
Richard Uhler66d874d2015-01-15 09:37:19 -0800319 // Neither odex_filename nor error_msg may be null.
Richard Uhlerb81881d2016-04-19 13:08:04 -0700320 static bool DexLocationToOdexFilename(const std::string& location,
321 InstructionSet isa,
322 std::string* odex_filename,
323 std::string* error_msg);
324
325 // Constructs the oat file name for the given dex location.
326 // Returns true on success, in which case oat_filename is set to the oat
327 // file name.
328 // Returns false on error, in which case error_msg describes the error and
329 // oat_filename is not changed.
330 // Neither oat_filename nor error_msg may be null.
Jiakai Zhang78d86b52022-05-26 17:24:17 +0100331 //
332 // Calling this function requires an active runtime.
Richard Uhlerb81881d2016-04-19 13:08:04 -0700333 static bool DexLocationToOatFilename(const std::string& location,
334 InstructionSet isa,
335 std::string* oat_filename,
336 std::string* error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800337
Jiakai Zhang78d86b52022-05-26 17:24:17 +0100338 // Same as above, but also takes `deny_art_apex_data_files` from input.
339 //
340 // Calling this function does not require an active runtime.
341 static bool DexLocationToOatFilename(const std::string& location,
342 InstructionSet isa,
343 bool deny_art_apex_data_files,
344 std::string* oat_filename,
345 std::string* error_msg);
346
Nicolas Geoffray88566952021-02-16 15:51:18 +0000347 // Computes the dex location and vdex filename. If the data directory of the process
David Brazdil35a3f6a2019-03-04 15:59:06 +0000348 // is known, creates an absolute path in that directory and tries to infer path
349 // of a corresponding vdex file. Otherwise only creates a basename dex_location
350 // from the combined checksums. Returns true if all out-arguments have been set.
Jiakai Zhang78d86b52022-05-26 17:24:17 +0100351 //
352 // Calling this function requires an active runtime.
David Brazdil35a3f6a2019-03-04 15:59:06 +0000353 static bool AnonymousDexVdexLocation(const std::vector<const DexFile::Header*>& dex_headers,
354 InstructionSet isa,
David Brazdil35a3f6a2019-03-04 15:59:06 +0000355 /* out */ std::string* dex_location,
356 /* out */ std::string* vdex_filename);
357
358 // Returns true if a filename (given as basename) is a name of a vdex for
359 // anonymous dex file(s) created by AnonymousDexVdexLocation.
360 static bool IsAnonymousVdexBasename(const std::string& basename);
361
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000362 bool ClassLoaderContextIsOkay(const OatFile& oat_file) const;
363
Jiakai Zhang7a5a95f2022-08-07 01:12:24 +0100364 // Validates the boot class path checksum of an OatFile.
365 bool ValidateBootClassPathChecksums(const OatFile& oat_file);
366
367 // Validates the given bootclasspath and bootclasspath checksums found in an oat header.
368 static bool ValidateBootClassPathChecksums(OatFileAssistantContext* ofa_context,
369 InstructionSet isa,
370 std::string_view oat_checksums,
371 std::string_view oat_boot_class_path,
372 /*out*/ std::string* error_msg);
373
Richard Uhler66d874d2015-01-15 09:37:19 -0800374 private:
Richard Uhler743bf362016-04-19 15:39:37 -0700375 class OatFileInfo {
376 public:
377 // Initially the info is for no file in particular. It will treat the
378 // file as out of date until Reset is called with a real filename to use
379 // the cache for.
Richard Uhler88bc6732016-11-14 14:38:03 +0000380 // Pass true for is_oat_location if the information associated with this
381 // OatFileInfo is for the oat location, as opposed to the odex location.
382 OatFileInfo(OatFileAssistant* oat_file_assistant, bool is_oat_location);
383
384 bool IsOatLocation();
Richard Uhler743bf362016-04-19 15:39:37 -0700385
386 const std::string* Filename();
Richard Uhler03bc6592016-11-22 09:42:04 +0000387
388 // Returns true if this oat file can be used for running code. The oat
389 // file can be used for running code as long as it is not out of date with
390 // respect to the dex code or boot image. An oat file that is out of date
391 // with respect to relocation is considered useable, because it's possible
392 // to interpret the dex code rather than run the unrelocated compiled
393 // code.
394 bool IsUseable();
395
396 // Returns the status of this oat file.
Richard Uhler743bf362016-04-19 15:39:37 -0700397 OatStatus Status();
Richard Uhler743bf362016-04-19 15:39:37 -0700398
Jiakai Zhangdbfa7992022-06-24 23:14:24 +0100399 // Return the DexOptNeeded value for this oat file with respect to the given target compilation
400 // filter and dexopt trigger.
Richard Uhler70a84262016-11-08 16:51:51 +0000401 DexOptNeeded GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter,
Jiakai Zhangdbfa7992022-06-24 23:14:24 +0100402 const DexOptTrigger dexopt_trigger);
Richard Uhler70a84262016-11-08 16:51:51 +0000403
Richard Uhler743bf362016-04-19 15:39:37 -0700404 // Returns the loaded file.
405 // Loads the file if needed. Returns null if the file failed to load.
406 // The caller shouldn't clean up or free the returned pointer.
407 const OatFile* GetFile();
408
Richard Uhler743bf362016-04-19 15:39:37 -0700409 // Returns true if the file is opened executable.
410 bool IsExecutable();
411
Richard Uhler743bf362016-04-19 15:39:37 -0700412 // Clear any cached information about the file that depends on the
413 // contents of the file. This does not reset the provided filename.
414 void Reset();
415
416 // Clear any cached information and switch to getting info about the oat
417 // file with the given filename.
Nicolas Geoffray30025092018-04-19 14:43:29 +0100418 void Reset(const std::string& filename,
419 bool use_fd,
420 int zip_fd = -1,
421 int vdex_fd = -1,
422 int oat_fd = -1);
Richard Uhler743bf362016-04-19 15:39:37 -0700423
Richard Uhler70a84262016-11-08 16:51:51 +0000424 // Release the loaded oat file for runtime use.
425 // Returns null if the oat file hasn't been loaded or is out of date.
426 // Ensures the returned file is not loaded executable if it has unuseable
427 // compiled code.
428 //
429 // After this call, no other methods of the OatFileInfo should be
430 // called, because access to the loaded oat file has been taken away from
431 // the OatFileInfo object.
432 std::unique_ptr<OatFile> ReleaseFileForUse();
433
434 private:
Jiakai Zhangdbfa7992022-06-24 23:14:24 +0100435 // Returns true if the oat file is usable but at least one dexopt trigger is matched. This
436 // function should only be called if the oat file is usable.
437 bool ShouldRecompileForFilter(CompilerFilter::Filter target,
438 const DexOptTrigger dexopt_trigger);
Richard Uhler70a84262016-11-08 16:51:51 +0000439
Richard Uhler743bf362016-04-19 15:39:37 -0700440 // Release the loaded oat file.
441 // Returns null if the oat file hasn't been loaded.
442 //
443 // After this call, no other methods of the OatFileInfo should be
444 // called, because access to the loaded oat file has been taken away from
445 // the OatFileInfo object.
446 std::unique_ptr<OatFile> ReleaseFile();
447
Richard Uhler743bf362016-04-19 15:39:37 -0700448 OatFileAssistant* oat_file_assistant_;
Richard Uhler88bc6732016-11-14 14:38:03 +0000449 const bool is_oat_location_;
Richard Uhler743bf362016-04-19 15:39:37 -0700450
451 bool filename_provided_ = false;
452 std::string filename_;
453
Nicolas Geoffray30025092018-04-19 14:43:29 +0100454 int zip_fd_ = -1;
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700455 int oat_fd_ = -1;
456 int vdex_fd_ = -1;
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700457 bool use_fd_ = false;
Shubham Ajmerab22dea02017-10-04 18:36:41 -0700458
Richard Uhler743bf362016-04-19 15:39:37 -0700459 bool load_attempted_ = false;
460 std::unique_ptr<OatFile> file_;
461
462 bool status_attempted_ = false;
Andreas Gamped9911ee2017-03-27 13:27:24 -0700463 OatStatus status_ = OatStatus::kOatCannotOpen;
Richard Uhler743bf362016-04-19 15:39:37 -0700464
465 // For debugging only.
466 // If this flag is set, the file has been released to the user and the
467 // OatFileInfo object is in a bad state and should no longer be used.
468 bool file_released_ = false;
469 };
Richard Uhler66d874d2015-01-15 09:37:19 -0800470
Richard Uhler88bc6732016-11-14 14:38:03 +0000471 // Return info for the best oat file.
472 OatFileInfo& GetBestInfo();
473
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700474 // Returns true when vdex/oat/odex files should be read from file descriptors.
475 // The method checks the value of zip_fd_, and if the value is valid, returns
476 // true. This is required to have a deterministic behavior around how different
477 // files are being read.
478 bool UseFdToReadFiles();
479
Richard Uhler2f27abd2017-01-31 14:02:34 +0000480 // Returns true if the dex checksums in the given oat file are up to date
481 // with respect to the dex location. If the dex checksums are not up to
482 // date, error_msg is updated with a message describing the problem.
483 bool DexChecksumUpToDate(const OatFile& file, std::string* error_msg);
484
Richard Uhler03bc6592016-11-22 09:42:04 +0000485 // Return the status for a given opened oat file with respect to the dex
486 // location.
487 OatStatus GivenOatFileStatus(const OatFile& file);
488
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000489 // Gets the dex checksums required for an up-to-date oat file.
Jiakai Zhangc372e792022-11-23 10:57:22 +0000490 // Returns cached_required_dex_checksums if the required checksums were located. Returns an empty
491 // list if `dex_location_` refers to a zip and there is no dex file in it. Returns nullptr if an
492 // error occurred. The caller shouldn't clean up or free the returned pointer.
493 const std::vector<uint32_t>* GetRequiredDexChecksums(std::string* error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800494
Jiakai Zhang78d86b52022-05-26 17:24:17 +0100495 // Returns whether there is at least one boot image usable.
496 bool IsPrimaryBootImageUsable();
497
Jiakai Zhangdbfa7992022-06-24 23:14:24 +0100498 // Returns the trigger for the deprecated overload of `GetDexOptNeeded`.
499 //
500 // Deprecated. Do not use in new code.
501 DexOptTrigger GetDexOptTrigger(CompilerFilter::Filter target_compiler_filter,
502 bool profile_changed,
503 bool downgrade);
504
Jiakai Zhang7a5a95f2022-08-07 01:12:24 +0100505 // Returns the pointer to the owned or unowned instance of OatFileAssistantContext.
506 OatFileAssistantContext* GetOatFileAssistantContext() {
507 if (std::holds_alternative<OatFileAssistantContext*>(ofa_context_)) {
508 return std::get<OatFileAssistantContext*>(ofa_context_);
509 } else {
510 return std::get<std::unique_ptr<OatFileAssistantContext>>(ofa_context_).get();
511 }
512 }
513
514 // The runtime options taken from the active runtime or the input.
515 //
516 // All member functions should get runtime options from this variable rather than referencing the
517 // active runtime. This is to allow OatFileAssistant to function without an active runtime.
518 const OatFileAssistantContext::RuntimeOptions& GetRuntimeOptions() {
519 return GetOatFileAssistantContext()->GetRuntimeOptions();
520 }
521
Jiakai Zhangc98ed722023-01-31 15:00:53 +0800522 // Returns whether the zip file only contains uncompressed dex.
523 bool ZipFileOnlyContainsUncompressedDex();
524
Richard Uhler740eec92015-10-15 15:12:23 -0700525 std::string dex_location_;
Richard Uhler66d874d2015-01-15 09:37:19 -0800526
Jiakai Zhangb4593412022-10-28 11:50:26 +0100527 // The class loader context to check against, or null representing that the check should be
528 // skipped.
Nicolas Geoffray525fa422021-04-19 07:50:35 +0000529 ClassLoaderContext* context_;
530
Calin Juravle357c66d2017-05-04 01:57:17 +0000531 // Whether or not the parent directory of the dex file is writable.
532 bool dex_parent_writable_ = false;
533
Richard Uhler66d874d2015-01-15 09:37:19 -0800534 // In a properly constructed OatFileAssistant object, isa_ should be either
535 // the 32 or 64 bit variant for the current device.
Vladimir Marko33bff252017-11-01 14:35:42 +0000536 const InstructionSet isa_ = InstructionSet::kNone;
Richard Uhler66d874d2015-01-15 09:37:19 -0800537
Richard Uhler66d874d2015-01-15 09:37:19 -0800538 // Whether we will attempt to load oat files executable.
539 bool load_executable_ = false;
540
Orion Hodson094b1cf2021-06-08 09:28:28 +0100541 // Whether only oat files from trusted locations are loaded executable.
542 const bool only_load_trusted_executable_ = false;
Jiakai Zhangc98ed722023-01-31 15:00:53 +0800543
544 // Cached value of whether the potential zip file only contains uncompressed dex.
545 // This should be accessed only by the ZipFileOnlyContainsUncompressedDex() method.
Nicolas Geoffray66ff8a82018-02-28 13:27:55 +0000546 bool zip_file_only_contains_uncompressed_dex_ = true;
Nicolas Geoffray29742602017-12-14 10:09:03 +0000547
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000548 // Cached value of the required dex checksums.
549 // This should be accessed only by the GetRequiredDexChecksums() method.
Jiakai Zhangc372e792022-11-23 10:57:22 +0000550 std::optional<std::vector<uint32_t>> cached_required_dex_checksums_;
551 std::string cached_required_dex_checksums_error_;
Richard Uhler69bcf2c2017-01-24 10:25:21 +0000552 bool required_dex_checksums_attempted_ = false;
Richard Uhler66d874d2015-01-15 09:37:19 -0800553
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000554 // The AOT-compiled file of an app when the APK of the app is in /data.
Richard Uhler743bf362016-04-19 15:39:37 -0700555 OatFileInfo odex_;
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000556 // The AOT-compiled file of an app when the APK of the app is on a read-only partition
557 // (for example /system).
Richard Uhler743bf362016-04-19 15:39:37 -0700558 OatFileInfo oat_;
Richard Uhler66d874d2015-01-15 09:37:19 -0800559
Nicolas Geoffray16f60dc2021-02-16 15:35:16 +0000560 // The vdex-only file next to `odex_` when `odex_' cannot be used (for example
561 // it is out of date).
562 OatFileInfo vdex_for_odex_;
563 // The vdex-only file next to 'oat_` when `oat_' cannot be used (for example
564 // it is out of date).
565 OatFileInfo vdex_for_oat_;
566
Nicolas Geoffray327cfcf2021-10-12 14:13:25 +0100567 // The vdex-only file next to the apk.
568 OatFileInfo dm_for_odex_;
569 OatFileInfo dm_for_oat_;
570
Shubham Ajmerac12bf4c2017-10-24 16:59:42 -0700571 // File descriptor corresponding to apk, dex file, or zip.
572 int zip_fd_;
573
Jiakai Zhang7a5a95f2022-08-07 01:12:24 +0100574 // Owned or unowned instance of OatFileAssistantContext.
575 std::variant<std::unique_ptr<OatFileAssistantContext>, OatFileAssistantContext*> ofa_context_;
Richard Uhler66d874d2015-01-15 09:37:19 -0800576
Calin Juravle357c66d2017-05-04 01:57:17 +0000577 friend class OatFileAssistantTest;
578
Richard Uhler66d874d2015-01-15 09:37:19 -0800579 DISALLOW_COPY_AND_ASSIGN(OatFileAssistant);
580};
581
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100582std::ostream& operator << (std::ostream& stream, const OatFileAssistant::OatStatus status);
583
Richard Uhler66d874d2015-01-15 09:37:19 -0800584} // namespace art
585
586#endif // ART_RUNTIME_OAT_FILE_ASSISTANT_H_