| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 1 | /* | 
|  | 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> | 
| Narayan Kamath | 8943c1d | 2016-05-02 13:14:48 +0100 | [diff] [blame] | 22 | #include <sstream> | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 23 | #include <string> | 
|  | 24 |  | 
|  | 25 | #include "arch/instruction_set.h" | 
|  | 26 | #include "base/scoped_flock.h" | 
|  | 27 | #include "base/unix_file/fd_file.h" | 
| Andreas Gampe | 29d38e7 | 2016-03-23 15:31:51 +0000 | [diff] [blame] | 28 | #include "compiler_filter.h" | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 29 | #include "oat_file.h" | 
|  | 30 | #include "os.h" | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 31 |  | 
|  | 32 | namespace art { | 
|  | 33 |  | 
| Mathieu Chartier | fbc3108 | 2016-01-24 11:59:56 -0800 | [diff] [blame] | 34 | namespace gc { | 
|  | 35 | namespace space { | 
|  | 36 | class ImageSpace; | 
|  | 37 | }  // namespace space | 
|  | 38 | }  // namespace gc | 
|  | 39 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 40 | // Class for assisting with oat file management. | 
|  | 41 | // | 
|  | 42 | // This class collects common utilities for determining the status of an oat | 
|  | 43 | // file on the device, updating the oat file, and loading the oat file. | 
|  | 44 | // | 
|  | 45 | // The oat file assistant is intended to be used with dex locations not on the | 
|  | 46 | // boot class path. See the IsInBootClassPath method for a way to check if the | 
|  | 47 | // dex location is in the boot class path. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 48 | class OatFileAssistant { | 
|  | 49 | public: | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 50 | enum DexOptNeeded { | 
| Richard Uhler | 7225a8d | 2016-11-22 10:12:03 +0000 | [diff] [blame] | 51 | // No dexopt should (or can) be done to update the apk/jar. | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 52 | // Matches Java: dalvik.system.DexFile.NO_DEXOPT_NEEDED = 0 | 
|  | 53 | kNoDexOptNeeded = 0, | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 54 |  | 
| Richard Uhler | 7225a8d | 2016-11-22 10:12:03 +0000 | [diff] [blame] | 55 | // dex2oat should be run to update the apk/jar from scratch. | 
|  | 56 | // Matches Java: dalvik.system.DexFile.DEX2OAT_FROM_SCRATCH = 1 | 
|  | 57 | kDex2OatFromScratch = 1, | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 58 |  | 
| Richard Uhler | 7225a8d | 2016-11-22 10:12:03 +0000 | [diff] [blame] | 59 | // dex2oat should be run to update the apk/jar because the existing code | 
|  | 60 | // is out of date with respect to the boot image. | 
|  | 61 | // Matches Java: dalvik.system.DexFile.DEX2OAT_FOR_BOOT_IMAGE | 
|  | 62 | kDex2OatForBootImage = 2, | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 63 |  | 
| Richard Uhler | 7225a8d | 2016-11-22 10:12:03 +0000 | [diff] [blame] | 64 | // dex2oat should be run to update the apk/jar because the existing code | 
|  | 65 | // is out of date with respect to the target compiler filter. | 
|  | 66 | // Matches Java: dalvik.system.DexFile.DEX2OAT_FOR_FILTER | 
|  | 67 | kDex2OatForFilter = 3, | 
|  | 68 |  | 
|  | 69 | // dex2oat should be run to update the apk/jar because the existing code | 
| Richard Uhler | 5923b52 | 2016-12-08 09:48:01 +0000 | [diff] [blame] | 70 | // is not relocated to match the boot image. | 
| Richard Uhler | 7225a8d | 2016-11-22 10:12:03 +0000 | [diff] [blame] | 71 | // Matches Java: dalvik.system.DexFile.DEX2OAT_FOR_RELOCATION | 
|  | 72 | kDex2OatForRelocation = 4, | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 73 | }; | 
|  | 74 |  | 
|  | 75 | enum OatStatus { | 
| Richard Uhler | 03bc659 | 2016-11-22 09:42:04 +0000 | [diff] [blame] | 76 | // kOatCannotOpen - The oat file cannot be opened, because it does not | 
|  | 77 | // exist, is unreadable, or otherwise corrupted. | 
|  | 78 | kOatCannotOpen, | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 79 |  | 
| Richard Uhler | 03bc659 | 2016-11-22 09:42:04 +0000 | [diff] [blame] | 80 | // kOatDexOutOfDate - The oat file is out of date with respect to the dex file. | 
|  | 81 | kOatDexOutOfDate, | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 82 |  | 
| Richard Uhler | 03bc659 | 2016-11-22 09:42:04 +0000 | [diff] [blame] | 83 | // kOatBootImageOutOfDate - The oat file is up to date with respect to the | 
|  | 84 | // dex file, but is out of date with respect to the boot image. | 
|  | 85 | kOatBootImageOutOfDate, | 
|  | 86 |  | 
|  | 87 | // kOatRelocationOutOfDate - The oat file is up to date with respect to | 
|  | 88 | // the dex file and boot image, but contains compiled code that has the | 
|  | 89 | // wrong patch delta with respect to the boot image. Patchoat should be | 
|  | 90 | // run on the oat file to update the patch delta of the compiled code to | 
|  | 91 | // match the boot image. | 
|  | 92 | kOatRelocationOutOfDate, | 
|  | 93 |  | 
|  | 94 | // kOatUpToDate - The oat file is completely up to date with respect to | 
|  | 95 | // the dex file and boot image. | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 96 | kOatUpToDate, | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 97 | }; | 
|  | 98 |  | 
|  | 99 | // Constructs an OatFileAssistant object to assist the oat file | 
|  | 100 | // corresponding to the given dex location with the target instruction set. | 
|  | 101 | // | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 102 | // The dex_location must not be null and should remain available and | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 103 | // unchanged for the duration of the lifetime of the OatFileAssistant object. | 
|  | 104 | // Typically the dex_location is the absolute path to the original, | 
|  | 105 | // un-optimized dex file. | 
|  | 106 | // | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 107 | // Note: Currently the dex_location must have an extension. | 
|  | 108 | // TODO: Relax this restriction? | 
|  | 109 | // | 
|  | 110 | // The isa should be either the 32 bit or 64 bit variant for the current | 
|  | 111 | // device. For example, on an arm device, use arm or arm64. An oat file can | 
|  | 112 | // be loaded executable only if the ISA matches the current runtime. | 
| Andreas Gampe | 29d38e7 | 2016-03-23 15:31:51 +0000 | [diff] [blame] | 113 | // | 
| Andreas Gampe | 29d38e7 | 2016-03-23 15:31:51 +0000 | [diff] [blame] | 114 | // load_executable should be true if the caller intends to try and load | 
|  | 115 | // executable code for this dex location. | 
| Calin Juravle | b077e15 | 2016-02-18 18:47:37 +0000 | [diff] [blame] | 116 | OatFileAssistant(const char* dex_location, | 
| Calin Juravle | b077e15 | 2016-02-18 18:47:37 +0000 | [diff] [blame] | 117 | const InstructionSet isa, | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 118 | bool load_executable); | 
|  | 119 |  | 
|  | 120 | // Constructs an OatFileAssistant, providing an explicit target oat_location | 
|  | 121 | // to use instead of the standard oat location. | 
| Calin Juravle | b077e15 | 2016-02-18 18:47:37 +0000 | [diff] [blame] | 122 | OatFileAssistant(const char* dex_location, | 
|  | 123 | const char* oat_location, | 
| Calin Juravle | b077e15 | 2016-02-18 18:47:37 +0000 | [diff] [blame] | 124 | const InstructionSet isa, | 
|  | 125 | bool load_executable); | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 126 |  | 
|  | 127 | ~OatFileAssistant(); | 
|  | 128 |  | 
|  | 129 | // Returns true if the dex location refers to an element of the boot class | 
|  | 130 | // path. | 
|  | 131 | bool IsInBootClassPath(); | 
|  | 132 |  | 
|  | 133 | // Obtains a lock on the target oat file. | 
|  | 134 | // Only one OatFileAssistant object can hold the lock for a target oat file | 
|  | 135 | // at a time. The Lock is released automatically when the OatFileAssistant | 
|  | 136 | // object goes out of scope. The Lock() method must not be called if the | 
|  | 137 | // lock has already been acquired. | 
|  | 138 | // | 
|  | 139 | // Returns true on success. | 
|  | 140 | // Returns false on error, in which case error_msg will contain more | 
|  | 141 | // information on the error. | 
|  | 142 | // | 
|  | 143 | // The 'error_msg' argument must not be null. | 
|  | 144 | // | 
|  | 145 | // This is intended to be used to avoid race conditions when multiple | 
|  | 146 | // processes generate oat files, such as when a foreground Activity and | 
|  | 147 | // a background Service both use DexClassLoaders pointing to the same dex | 
|  | 148 | // file. | 
|  | 149 | bool Lock(std::string* error_msg); | 
|  | 150 |  | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 151 | // Return what action needs to be taken to produce up-to-date code for this | 
| Andreas Gampe | 29d38e7 | 2016-03-23 15:31:51 +0000 | [diff] [blame] | 152 | // dex location that is at least as good as an oat file generated with the | 
| Richard Uhler | d1472a2 | 2016-04-15 15:18:56 -0700 | [diff] [blame] | 153 | // given compiler filter. profile_changed should be true to indicate the | 
|  | 154 | // profile has recently changed for this dex location. | 
| Richard Uhler | 7225a8d | 2016-11-22 10:12:03 +0000 | [diff] [blame] | 155 | // Returns a positive status code if the status refers to the oat file in | 
|  | 156 | // the oat location. Returns a negative status code if the status refers to | 
|  | 157 | // the oat file in the odex location. | 
|  | 158 | int GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter, bool profile_changed = false); | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 159 |  | 
| Richard Uhler | 01be681 | 2016-05-17 10:34:52 -0700 | [diff] [blame] | 160 | // Returns true if there is up-to-date code for this dex location, | 
|  | 161 | // irrespective of the compiler filter of the up-to-date code. | 
|  | 162 | bool IsUpToDate(); | 
|  | 163 |  | 
| Richard Uhler | 1e86061 | 2016-03-30 12:17:55 -0700 | [diff] [blame] | 164 | // Return code used when attempting to generate updated code. | 
|  | 165 | enum ResultOfAttemptToUpdate { | 
|  | 166 | kUpdateFailed,        // We tried making the code up to date, but | 
|  | 167 | // encountered an unexpected failure. | 
|  | 168 | kUpdateNotAttempted,  // We wanted to update the code, but determined we | 
|  | 169 | // should not make the attempt. | 
|  | 170 | kUpdateSucceeded      // We successfully made the code up to date | 
|  | 171 | // (possibly by doing nothing). | 
|  | 172 | }; | 
|  | 173 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 174 | // Attempts to generate or relocate the oat file as needed to make it up to | 
| Richard Uhler | f4b3487 | 2016-04-13 11:03:46 -0700 | [diff] [blame] | 175 | // date based on the current runtime and compiler options. | 
| Richard Uhler | d1472a2 | 2016-04-15 15:18:56 -0700 | [diff] [blame] | 176 | // profile_changed should be true to indicate the profile has recently | 
|  | 177 | // changed for this dex location. | 
|  | 178 | // | 
|  | 179 | // Returns the result of attempting to update the code. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 180 | // | 
| Richard Uhler | 1e86061 | 2016-03-30 12:17:55 -0700 | [diff] [blame] | 181 | // If the result is not kUpdateSucceeded, the value of error_msg will be set | 
|  | 182 | // to a string describing why there was a failure or the update was not | 
|  | 183 | // attempted. error_msg must not be null. | 
| Richard Uhler | d1472a2 | 2016-04-15 15:18:56 -0700 | [diff] [blame] | 184 | ResultOfAttemptToUpdate MakeUpToDate(bool profile_changed, std::string* error_msg); | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 185 |  | 
|  | 186 | // Returns an oat file that can be used for loading dex files. | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 187 | // Returns null if no suitable oat file was found. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 188 | // | 
|  | 189 | // After this call, no other methods of the OatFileAssistant should be | 
|  | 190 | // called, because access to the loaded oat file has been taken away from | 
|  | 191 | // the OatFileAssistant object. | 
|  | 192 | std::unique_ptr<OatFile> GetBestOatFile(); | 
|  | 193 |  | 
| Richard Uhler | 46cc64f | 2016-11-14 14:53:55 +0000 | [diff] [blame] | 194 | // Returns a human readable description of the status of the code for the | 
|  | 195 | // dex file. The returned description is for debugging purposes only. | 
|  | 196 | std::string GetStatusDump(); | 
|  | 197 |  | 
| Mathieu Chartier | fbc3108 | 2016-01-24 11:59:56 -0800 | [diff] [blame] | 198 | // Open and returns an image space associated with the oat file. | 
| Andreas Gampe | a463b6a | 2016-08-12 21:53:32 -0700 | [diff] [blame] | 199 | static std::unique_ptr<gc::space::ImageSpace> OpenImageSpace(const OatFile* oat_file); | 
| Mathieu Chartier | fbc3108 | 2016-01-24 11:59:56 -0800 | [diff] [blame] | 200 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 201 | // Loads the dex files in the given oat file for the given dex location. | 
|  | 202 | // The oat file should be up to date for the given dex location. | 
|  | 203 | // This loads multiple dex files in the case of multidex. | 
|  | 204 | // Returns an empty vector if no dex files for that location could be loaded | 
|  | 205 | // from the oat file. | 
|  | 206 | // | 
|  | 207 | // The caller is responsible for freeing the dex_files returned, if any. The | 
|  | 208 | // dex_files will only remain valid as long as the oat_file is valid. | 
|  | 209 | static std::vector<std::unique_ptr<const DexFile>> LoadDexFiles( | 
|  | 210 | const OatFile& oat_file, const char* dex_location); | 
|  | 211 |  | 
| Richard Uhler | 9b994ea | 2015-06-24 08:44:19 -0700 | [diff] [blame] | 212 | // Returns true if there are dex files in the original dex location that can | 
|  | 213 | // be compiled with dex2oat for this dex location. | 
|  | 214 | // Returns false if there is no original dex file, or if the original dex | 
|  | 215 | // file is an apk/zip without a classes.dex entry. | 
|  | 216 | bool HasOriginalDexFiles(); | 
|  | 217 |  | 
| Richard Uhler | 6343411 | 2015-03-16 14:32:16 -0700 | [diff] [blame] | 218 | // If the dex file has been installed with a compiled oat file alongside | 
|  | 219 | // it, the compiled oat file will have the extension .odex, and is referred | 
|  | 220 | // to as the odex file. It is called odex for legacy reasons; the file is | 
|  | 221 | // really an oat file. The odex file will often, but not always, have a | 
|  | 222 | // patch delta of 0 and need to be relocated before use for the purposes of | 
|  | 223 | // ASLR. The odex file is treated as if it were read-only. | 
| Richard Uhler | 03bc659 | 2016-11-22 09:42:04 +0000 | [diff] [blame] | 224 | // | 
|  | 225 | // Returns the status of the odex file for the dex location. | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 226 | OatStatus OdexFileStatus(); | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 227 |  | 
|  | 228 | // When the dex files is compiled on the target device, the oat file is the | 
|  | 229 | // result. The oat file will have been relocated to some | 
|  | 230 | // (possibly-out-of-date) offset for ASLR. | 
| Richard Uhler | 03bc659 | 2016-11-22 09:42:04 +0000 | [diff] [blame] | 231 | // | 
|  | 232 | // Returns the status of the oat file for the dex location. | 
| Richard Uhler | 95abd04 | 2015-03-24 09:51:28 -0700 | [diff] [blame] | 233 | OatStatus OatFileStatus(); | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 234 |  | 
| Richard Uhler | f4b3487 | 2016-04-13 11:03:46 -0700 | [diff] [blame] | 235 | // Generate the oat file from the dex file using the current runtime | 
|  | 236 | // compiler options. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 237 | // This does not check the current status before attempting to generate the | 
|  | 238 | // oat file. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 239 | // | 
| Richard Uhler | 1e86061 | 2016-03-30 12:17:55 -0700 | [diff] [blame] | 240 | // If the result is not kUpdateSucceeded, the value of error_msg will be set | 
|  | 241 | // to a string describing why there was a failure or the update was not | 
|  | 242 | // attempted. error_msg must not be null. | 
| Richard Uhler | f4b3487 | 2016-04-13 11:03:46 -0700 | [diff] [blame] | 243 | ResultOfAttemptToUpdate GenerateOatFile(std::string* error_msg); | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 244 |  | 
|  | 245 | // Executes dex2oat using the current runtime configuration overridden with | 
|  | 246 | // the given arguments. This does not check to see if dex2oat is enabled in | 
|  | 247 | // the runtime configuration. | 
|  | 248 | // Returns true on success. | 
|  | 249 | // | 
|  | 250 | // If there is a failure, the value of error_msg will be set to a string | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 251 | // describing why there was failure. error_msg must not be null. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 252 | // | 
|  | 253 | // TODO: The OatFileAssistant probably isn't the right place to have this | 
|  | 254 | // function. | 
|  | 255 | static bool Dex2Oat(const std::vector<std::string>& args, std::string* error_msg); | 
|  | 256 |  | 
|  | 257 | // Constructs the odex file name for the given dex location. | 
|  | 258 | // Returns true on success, in which case odex_filename is set to the odex | 
|  | 259 | // file name. | 
| Richard Uhler | e8e48ae | 2016-04-19 12:41:04 -0700 | [diff] [blame] | 260 | // Returns false on error, in which case error_msg describes the error and | 
|  | 261 | // odex_filename is not changed. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 262 | // Neither odex_filename nor error_msg may be null. | 
| Richard Uhler | b81881d | 2016-04-19 13:08:04 -0700 | [diff] [blame] | 263 | static bool DexLocationToOdexFilename(const std::string& location, | 
|  | 264 | InstructionSet isa, | 
|  | 265 | std::string* odex_filename, | 
|  | 266 | std::string* error_msg); | 
|  | 267 |  | 
|  | 268 | // Constructs the oat file name for the given dex location. | 
|  | 269 | // Returns true on success, in which case oat_filename is set to the oat | 
|  | 270 | // file name. | 
|  | 271 | // Returns false on error, in which case error_msg describes the error and | 
|  | 272 | // oat_filename is not changed. | 
|  | 273 | // Neither oat_filename nor error_msg may be null. | 
|  | 274 | static bool DexLocationToOatFilename(const std::string& location, | 
|  | 275 | InstructionSet isa, | 
|  | 276 | std::string* oat_filename, | 
|  | 277 | std::string* error_msg); | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 278 |  | 
| Jeff Hao | fd336c3 | 2016-04-07 19:46:31 -0700 | [diff] [blame] | 279 | static uint32_t CalculateCombinedImageChecksum(InstructionSet isa = kRuntimeISA); | 
| Jeff Hao | b11ffb7 | 2016-04-07 15:40:54 -0700 | [diff] [blame] | 280 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 281 | private: | 
|  | 282 | struct ImageInfo { | 
|  | 283 | uint32_t oat_checksum = 0; | 
|  | 284 | uintptr_t oat_data_begin = 0; | 
|  | 285 | int32_t patch_delta = 0; | 
|  | 286 | std::string location; | 
|  | 287 | }; | 
|  | 288 |  | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 289 | class OatFileInfo { | 
|  | 290 | public: | 
|  | 291 | // Initially the info is for no file in particular. It will treat the | 
|  | 292 | // file as out of date until Reset is called with a real filename to use | 
|  | 293 | // the cache for. | 
| Richard Uhler | 88bc673 | 2016-11-14 14:38:03 +0000 | [diff] [blame] | 294 | // Pass true for is_oat_location if the information associated with this | 
|  | 295 | // OatFileInfo is for the oat location, as opposed to the odex location. | 
|  | 296 | OatFileInfo(OatFileAssistant* oat_file_assistant, bool is_oat_location); | 
|  | 297 |  | 
|  | 298 | bool IsOatLocation(); | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 299 |  | 
|  | 300 | const std::string* Filename(); | 
| Richard Uhler | 03bc659 | 2016-11-22 09:42:04 +0000 | [diff] [blame] | 301 |  | 
|  | 302 | // Returns true if this oat file can be used for running code. The oat | 
|  | 303 | // file can be used for running code as long as it is not out of date with | 
|  | 304 | // respect to the dex code or boot image. An oat file that is out of date | 
|  | 305 | // with respect to relocation is considered useable, because it's possible | 
|  | 306 | // to interpret the dex code rather than run the unrelocated compiled | 
|  | 307 | // code. | 
|  | 308 | bool IsUseable(); | 
|  | 309 |  | 
|  | 310 | // Returns the status of this oat file. | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 311 | OatStatus Status(); | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 312 |  | 
| Richard Uhler | 70a8426 | 2016-11-08 16:51:51 +0000 | [diff] [blame] | 313 | // Return the DexOptNeeded value for this oat file with respect to the | 
|  | 314 | // given target_compilation_filter. | 
|  | 315 | // profile_changed should be true to indicate the profile has recently | 
|  | 316 | // changed for this dex location. | 
| Richard Uhler | 70a8426 | 2016-11-08 16:51:51 +0000 | [diff] [blame] | 317 | DexOptNeeded GetDexOptNeeded(CompilerFilter::Filter target_compiler_filter, | 
|  | 318 | bool profile_changed); | 
|  | 319 |  | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 320 | // Returns the loaded file. | 
|  | 321 | // Loads the file if needed. Returns null if the file failed to load. | 
|  | 322 | // The caller shouldn't clean up or free the returned pointer. | 
|  | 323 | const OatFile* GetFile(); | 
|  | 324 |  | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 325 | // Returns true if the file is opened executable. | 
|  | 326 | bool IsExecutable(); | 
|  | 327 |  | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 328 | // Clear any cached information about the file that depends on the | 
|  | 329 | // contents of the file. This does not reset the provided filename. | 
|  | 330 | void Reset(); | 
|  | 331 |  | 
|  | 332 | // Clear any cached information and switch to getting info about the oat | 
|  | 333 | // file with the given filename. | 
|  | 334 | void Reset(const std::string& filename); | 
|  | 335 |  | 
| Richard Uhler | 70a8426 | 2016-11-08 16:51:51 +0000 | [diff] [blame] | 336 | // Release the loaded oat file for runtime use. | 
|  | 337 | // Returns null if the oat file hasn't been loaded or is out of date. | 
|  | 338 | // Ensures the returned file is not loaded executable if it has unuseable | 
|  | 339 | // compiled code. | 
|  | 340 | // | 
|  | 341 | // After this call, no other methods of the OatFileInfo should be | 
|  | 342 | // called, because access to the loaded oat file has been taken away from | 
|  | 343 | // the OatFileInfo object. | 
|  | 344 | std::unique_ptr<OatFile> ReleaseFileForUse(); | 
|  | 345 |  | 
|  | 346 | private: | 
|  | 347 | // Returns true if the compiler filter used to generate the file is at | 
|  | 348 | // least as good as the given target filter. profile_changed should be | 
|  | 349 | // true to indicate the profile has recently changed for this dex | 
|  | 350 | // location. | 
|  | 351 | bool CompilerFilterIsOkay(CompilerFilter::Filter target, bool profile_changed); | 
|  | 352 |  | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 353 | // Release the loaded oat file. | 
|  | 354 | // Returns null if the oat file hasn't been loaded. | 
|  | 355 | // | 
|  | 356 | // After this call, no other methods of the OatFileInfo should be | 
|  | 357 | // called, because access to the loaded oat file has been taken away from | 
|  | 358 | // the OatFileInfo object. | 
|  | 359 | std::unique_ptr<OatFile> ReleaseFile(); | 
|  | 360 |  | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 361 | OatFileAssistant* oat_file_assistant_; | 
| Richard Uhler | 88bc673 | 2016-11-14 14:38:03 +0000 | [diff] [blame] | 362 | const bool is_oat_location_; | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 363 |  | 
|  | 364 | bool filename_provided_ = false; | 
|  | 365 | std::string filename_; | 
|  | 366 |  | 
|  | 367 | bool load_attempted_ = false; | 
|  | 368 | std::unique_ptr<OatFile> file_; | 
|  | 369 |  | 
|  | 370 | bool status_attempted_ = false; | 
|  | 371 | OatStatus status_; | 
|  | 372 |  | 
|  | 373 | // For debugging only. | 
|  | 374 | // If this flag is set, the file has been released to the user and the | 
|  | 375 | // OatFileInfo object is in a bad state and should no longer be used. | 
|  | 376 | bool file_released_ = false; | 
|  | 377 | }; | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 378 |  | 
| Richard Uhler | 88bc673 | 2016-11-14 14:38:03 +0000 | [diff] [blame] | 379 | // Return info for the best oat file. | 
|  | 380 | OatFileInfo& GetBestInfo(); | 
|  | 381 |  | 
| Richard Uhler | 2f27abd | 2017-01-31 14:02:34 +0000 | [diff] [blame^] | 382 | // Returns true if the dex checksums in the given vdex file are up to date | 
|  | 383 | // with respect to the dex location. If the dex checksums are not up to | 
|  | 384 | // date, error_msg is updated with a message describing the problem. | 
|  | 385 | bool DexChecksumUpToDate(const VdexFile& file, std::string* error_msg); | 
|  | 386 |  | 
|  | 387 | // Returns true if the dex checksums in the given oat file are up to date | 
|  | 388 | // with respect to the dex location. If the dex checksums are not up to | 
|  | 389 | // date, error_msg is updated with a message describing the problem. | 
|  | 390 | bool DexChecksumUpToDate(const OatFile& file, std::string* error_msg); | 
|  | 391 |  | 
| Richard Uhler | 03bc659 | 2016-11-22 09:42:04 +0000 | [diff] [blame] | 392 | // Return the status for a given opened oat file with respect to the dex | 
|  | 393 | // location. | 
|  | 394 | OatStatus GivenOatFileStatus(const OatFile& file); | 
|  | 395 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 396 | // Returns the current image location. | 
|  | 397 | // Returns an empty string if the image location could not be retrieved. | 
|  | 398 | // | 
|  | 399 | // TODO: This method should belong with an image file manager, not | 
|  | 400 | // the oat file assistant. | 
|  | 401 | static std::string ImageLocation(); | 
|  | 402 |  | 
|  | 403 | // Gets the dex checksum required for an up-to-date oat file. | 
|  | 404 | // Returns dex_checksum if a required checksum was located. Returns | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 405 | // null if the required checksum was not found. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 406 | // The caller shouldn't clean up or free the returned pointer. | 
| Richard Uhler | 9b994ea | 2015-06-24 08:44:19 -0700 | [diff] [blame] | 407 | // This sets the has_original_dex_files_ field to true if a checksum was | 
|  | 408 | // found for the dex_location_ dex file. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 409 | const uint32_t* GetRequiredDexChecksum(); | 
|  | 410 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 411 | // Returns the loaded image info. | 
| Mathieu Chartier | 2cebb24 | 2015-04-21 16:50:40 -0700 | [diff] [blame] | 412 | // Loads the image info if needed. Returns null if the image info failed | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 413 | // to load. | 
|  | 414 | // The caller shouldn't clean up or free the returned pointer. | 
|  | 415 | const ImageInfo* GetImageInfo(); | 
|  | 416 |  | 
| Jeff Hao | b11ffb7 | 2016-04-07 15:40:54 -0700 | [diff] [blame] | 417 | uint32_t GetCombinedImageChecksum(); | 
|  | 418 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 419 | // To implement Lock(), we lock a dummy file where the oat file would go | 
|  | 420 | // (adding ".flock" to the target file name) and retain the lock for the | 
|  | 421 | // remaining lifetime of the OatFileAssistant object. | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 422 | ScopedFlock flock_; | 
|  | 423 |  | 
| Richard Uhler | 740eec9 | 2015-10-15 15:12:23 -0700 | [diff] [blame] | 424 | std::string dex_location_; | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 425 |  | 
|  | 426 | // In a properly constructed OatFileAssistant object, isa_ should be either | 
|  | 427 | // the 32 or 64 bit variant for the current device. | 
|  | 428 | const InstructionSet isa_ = kNone; | 
|  | 429 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 430 | // Whether we will attempt to load oat files executable. | 
|  | 431 | bool load_executable_ = false; | 
|  | 432 |  | 
|  | 433 | // Cached value of the required dex checksum. | 
|  | 434 | // This should be accessed only by the GetRequiredDexChecksum() method. | 
| Richard Uhler | 9b994ea | 2015-06-24 08:44:19 -0700 | [diff] [blame] | 435 | uint32_t cached_required_dex_checksum_; | 
|  | 436 | bool required_dex_checksum_attempted_ = false; | 
|  | 437 | bool required_dex_checksum_found_; | 
|  | 438 | bool has_original_dex_files_; | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 439 |  | 
| Richard Uhler | 743bf36 | 2016-04-19 15:39:37 -0700 | [diff] [blame] | 440 | OatFileInfo odex_; | 
|  | 441 | OatFileInfo oat_; | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 442 |  | 
|  | 443 | // Cached value of the image info. | 
|  | 444 | // Use the GetImageInfo method rather than accessing these directly. | 
|  | 445 | // TODO: The image info should probably be moved out of the oat file | 
|  | 446 | // assistant to an image file manager. | 
|  | 447 | bool image_info_load_attempted_ = false; | 
|  | 448 | bool image_info_load_succeeded_ = false; | 
|  | 449 | ImageInfo cached_image_info_; | 
| Jeff Hao | b11ffb7 | 2016-04-07 15:40:54 -0700 | [diff] [blame] | 450 | uint32_t combined_image_checksum_ = 0; | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 451 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 452 | DISALLOW_COPY_AND_ASSIGN(OatFileAssistant); | 
|  | 453 | }; | 
|  | 454 |  | 
| Narayan Kamath | 8943c1d | 2016-05-02 13:14:48 +0100 | [diff] [blame] | 455 | std::ostream& operator << (std::ostream& stream, const OatFileAssistant::OatStatus status); | 
|  | 456 |  | 
| Richard Uhler | 66d874d | 2015-01-15 09:37:19 -0800 | [diff] [blame] | 457 | }  // namespace art | 
|  | 458 |  | 
|  | 459 | #endif  // ART_RUNTIME_OAT_FILE_ASSISTANT_H_ |