blob: b92e05036b6803fa45c8f3ea7a6afd99898335b1 [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#include "oat_file_assistant.h"
18
Richard Uhler66d874d2015-01-15 09:37:19 -080019#include <sys/stat.h>
Richard Uhler66d874d2015-01-15 09:37:19 -080020#include "base/logging.h"
21#include "base/stringprintf.h"
Narayan Kamath8943c1d2016-05-02 13:14:48 +010022#include "compiler_filter.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080023#include "class_linker.h"
24#include "gc/heap.h"
25#include "gc/space/image_space.h"
26#include "image.h"
27#include "oat.h"
28#include "os.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080029#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070030#include "scoped_thread_state_change-inl.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080031#include "utils.h"
32
33namespace art {
34
Narayan Kamath8943c1d2016-05-02 13:14:48 +010035std::ostream& operator << (std::ostream& stream, const OatFileAssistant::OatStatus status) {
36 switch (status) {
37 case OatFileAssistant::kOatOutOfDate:
38 stream << "kOatOutOfDate";
39 break;
40 case OatFileAssistant::kOatUpToDate:
41 stream << "kOatUpToDate";
42 break;
43 case OatFileAssistant::kOatNeedsRelocation:
44 stream << "kOatNeedsRelocation";
45 break;
46 default:
47 UNREACHABLE();
48 }
49
50 return stream;
51}
52
Richard Uhler66d874d2015-01-15 09:37:19 -080053OatFileAssistant::OatFileAssistant(const char* dex_location,
54 const InstructionSet isa,
55 bool load_executable)
Richard Uhlerd1472a22016-04-15 15:18:56 -070056 : OatFileAssistant(dex_location, nullptr, isa, load_executable)
Calin Juravleb077e152016-02-18 18:47:37 +000057{ }
Richard Uhler66d874d2015-01-15 09:37:19 -080058
59OatFileAssistant::OatFileAssistant(const char* dex_location,
60 const char* oat_location,
61 const InstructionSet isa,
62 bool load_executable)
Richard Uhler743bf362016-04-19 15:39:37 -070063 : isa_(isa), load_executable_(load_executable), odex_(this), oat_(this) {
Richard Uhler740eec92015-10-15 15:12:23 -070064 CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location";
65 dex_location_.assign(dex_location);
66
Richard Uhler66d874d2015-01-15 09:37:19 -080067 if (load_executable_ && isa != kRuntimeISA) {
68 LOG(WARNING) << "OatFileAssistant: Load executable specified, "
69 << "but isa is not kRuntimeISA. Will not attempt to load executable.";
70 load_executable_ = false;
71 }
72
Richard Uhler743bf362016-04-19 15:39:37 -070073 // Get the odex filename.
Richard Uhlerd684f522016-04-19 13:24:41 -070074 std::string error_msg;
Richard Uhler743bf362016-04-19 15:39:37 -070075 std::string odex_file_name;
76 if (DexLocationToOdexFilename(dex_location_, isa_, &odex_file_name, &error_msg)) {
77 odex_.Reset(odex_file_name);
78 } else {
Richard Uhlerd684f522016-04-19 13:24:41 -070079 LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
80 }
81
Richard Uhler743bf362016-04-19 15:39:37 -070082 // Get the oat filename.
Richard Uhler66d874d2015-01-15 09:37:19 -080083 if (oat_location != nullptr) {
Richard Uhler743bf362016-04-19 15:39:37 -070084 oat_.Reset(oat_location);
Richard Uhlerd684f522016-04-19 13:24:41 -070085 } else {
Richard Uhler743bf362016-04-19 15:39:37 -070086 std::string oat_file_name;
87 if (DexLocationToOatFilename(dex_location_, isa_, &oat_file_name, &error_msg)) {
88 oat_.Reset(oat_file_name);
89 } else {
Richard Uhlerd684f522016-04-19 13:24:41 -070090 LOG(WARNING) << "Failed to determine oat file name for dex location "
91 << dex_location_ << ": " << error_msg;
92 }
Richard Uhler66d874d2015-01-15 09:37:19 -080093 }
Richard Uhler66d874d2015-01-15 09:37:19 -080094}
95
96OatFileAssistant::~OatFileAssistant() {
97 // Clean up the lock file.
Richard Uhler581f4e92015-05-07 10:19:35 -070098 if (flock_.HasFile()) {
Vladimir Marko66fdcbd2016-04-05 14:19:08 +010099 unlink(flock_.GetFile()->GetPath().c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800100 }
101}
102
103bool OatFileAssistant::IsInBootClassPath() {
104 // Note: We check the current boot class path, regardless of the ISA
105 // specified by the user. This is okay, because the boot class path should
106 // be the same for all ISAs.
107 // TODO: Can we verify the boot class path is the same for all ISAs?
108 Runtime* runtime = Runtime::Current();
109 ClassLinker* class_linker = runtime->GetClassLinker();
110 const auto& boot_class_path = class_linker->GetBootClassPath();
111 for (size_t i = 0; i < boot_class_path.size(); i++) {
Richard Uhler740eec92015-10-15 15:12:23 -0700112 if (boot_class_path[i]->GetLocation() == dex_location_) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800113 VLOG(oat) << "Dex location " << dex_location_ << " is in boot class path";
114 return true;
115 }
116 }
117 return false;
118}
119
120bool OatFileAssistant::Lock(std::string* error_msg) {
121 CHECK(error_msg != nullptr);
Richard Uhler581f4e92015-05-07 10:19:35 -0700122 CHECK(!flock_.HasFile()) << "OatFileAssistant::Lock already acquired";
Richard Uhler66d874d2015-01-15 09:37:19 -0800123
Richard Uhler743bf362016-04-19 15:39:37 -0700124 const std::string* oat_file_name = oat_.Filename();
125 if (oat_file_name == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800126 *error_msg = "Failed to determine lock file";
127 return false;
128 }
Richard Uhler743bf362016-04-19 15:39:37 -0700129 std::string lock_file_name = *oat_file_name + ".flock";
Richard Uhler66d874d2015-01-15 09:37:19 -0800130
Richard Uhler581f4e92015-05-07 10:19:35 -0700131 if (!flock_.Init(lock_file_name.c_str(), error_msg)) {
Vladimir Marko66fdcbd2016-04-05 14:19:08 +0100132 unlink(lock_file_name.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800133 return false;
134 }
135 return true;
136}
137
Richard Uhlerd1472a22016-04-15 15:18:56 -0700138OatFileAssistant::DexOptNeeded
Richard Uhler743bf362016-04-19 15:39:37 -0700139OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target, bool profile_changed) {
Richard Uhler3e580bc2016-11-08 16:23:07 +0000140 if (oat_.Status() != kOatOutOfDate) {
Richard Uhler70a84262016-11-08 16:51:51 +0000141 DexOptNeeded dexopt_needed = oat_.GetDexOptNeeded(target, profile_changed);
142 if (dexopt_needed == kPatchOatNeeded) {
143 dexopt_needed = kSelfPatchOatNeeded;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000144 }
Richard Uhler70a84262016-11-08 16:51:51 +0000145 return dexopt_needed;
Richard Uhler66d874d2015-01-15 09:37:19 -0800146 }
Richard Uhler70a84262016-11-08 16:51:51 +0000147 return odex_.GetDexOptNeeded(target, profile_changed);
Richard Uhler66d874d2015-01-15 09:37:19 -0800148}
149
Richard Uhlerf4b34872016-04-13 11:03:46 -0700150// Figure out the currently specified compile filter option in the runtime.
151// Returns true on success, false if the compiler filter is invalid, in which
152// case error_msg describes the problem.
153static bool GetRuntimeCompilerFilterOption(CompilerFilter::Filter* filter,
154 std::string* error_msg) {
155 CHECK(filter != nullptr);
156 CHECK(error_msg != nullptr);
157
158 *filter = CompilerFilter::kDefaultCompilerFilter;
159 for (StringPiece option : Runtime::Current()->GetCompilerOptions()) {
160 if (option.starts_with("--compiler-filter=")) {
161 const char* compiler_filter_string = option.substr(strlen("--compiler-filter=")).data();
162 if (!CompilerFilter::ParseCompilerFilter(compiler_filter_string, filter)) {
163 *error_msg = std::string("Unknown --compiler-filter value: ")
164 + std::string(compiler_filter_string);
165 return false;
166 }
167 }
168 }
169 return true;
170}
171
Richard Uhler01be6812016-05-17 10:34:52 -0700172bool OatFileAssistant::IsUpToDate() {
Richard Uhler3e580bc2016-11-08 16:23:07 +0000173 return oat_.Status() == kOatUpToDate || odex_.Status() == kOatUpToDate;
Richard Uhler01be6812016-05-17 10:34:52 -0700174}
175
Richard Uhler1e860612016-03-30 12:17:55 -0700176OatFileAssistant::ResultOfAttemptToUpdate
Richard Uhlerd1472a22016-04-15 15:18:56 -0700177OatFileAssistant::MakeUpToDate(bool profile_changed, std::string* error_msg) {
Richard Uhlerf4b34872016-04-13 11:03:46 -0700178 CompilerFilter::Filter target;
179 if (!GetRuntimeCompilerFilterOption(&target, error_msg)) {
180 return kUpdateNotAttempted;
181 }
182
Richard Uhlerd1472a22016-04-15 15:18:56 -0700183 switch (GetDexOptNeeded(target, profile_changed)) {
Richard Uhler1e860612016-03-30 12:17:55 -0700184 case kNoDexOptNeeded: return kUpdateSucceeded;
Richard Uhlerf4b34872016-04-13 11:03:46 -0700185 case kDex2OatNeeded: return GenerateOatFile(error_msg);
Richard Uhler743bf362016-04-19 15:39:37 -0700186 case kPatchOatNeeded: return RelocateOatFile(odex_.Filename(), error_msg);
187 case kSelfPatchOatNeeded: return RelocateOatFile(oat_.Filename(), error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800188 }
189 UNREACHABLE();
190}
191
192std::unique_ptr<OatFile> OatFileAssistant::GetBestOatFile() {
Richard Uhler3e580bc2016-11-08 16:23:07 +0000193 if (oat_.Status() != kOatOutOfDate) {
Richard Uhler70a84262016-11-08 16:51:51 +0000194 return oat_.ReleaseFileForUse();
Richard Uhler5f946da2015-07-17 12:28:32 -0700195 }
Richard Uhler70a84262016-11-08 16:51:51 +0000196 return odex_.ReleaseFileForUse();
Richard Uhler66d874d2015-01-15 09:37:19 -0800197}
198
199std::vector<std::unique_ptr<const DexFile>> OatFileAssistant::LoadDexFiles(
200 const OatFile& oat_file, const char* dex_location) {
201 std::vector<std::unique_ptr<const DexFile>> dex_files;
202
203 // Load the primary dex file.
204 std::string error_msg;
205 const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(
Richard Uhler9a37efc2016-08-05 16:32:55 -0700206 dex_location, nullptr, &error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800207 if (oat_dex_file == nullptr) {
Richard Uhler9a37efc2016-08-05 16:32:55 -0700208 LOG(WARNING) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800209 return std::vector<std::unique_ptr<const DexFile>>();
210 }
211
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700212 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800213 if (dex_file.get() == nullptr) {
214 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
215 return std::vector<std::unique_ptr<const DexFile>>();
216 }
217 dex_files.push_back(std::move(dex_file));
218
219 // Load secondary multidex files
Andreas Gampe90e34042015-04-27 20:01:52 -0700220 for (size_t i = 1; ; i++) {
221 std::string secondary_dex_location = DexFile::GetMultiDexLocation(i, dex_location);
Richard Uhler9a37efc2016-08-05 16:32:55 -0700222 oat_dex_file = oat_file.GetOatDexFile(secondary_dex_location.c_str(), nullptr);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700223 if (oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800224 // There are no more secondary dex files to load.
225 break;
226 }
227
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700228 dex_file = oat_dex_file->OpenDexFile(&error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800229 if (dex_file.get() == nullptr) {
230 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
231 return std::vector<std::unique_ptr<const DexFile>>();
232 }
233 dex_files.push_back(std::move(dex_file));
234 }
235 return dex_files;
236}
237
Richard Uhler9b994ea2015-06-24 08:44:19 -0700238bool OatFileAssistant::HasOriginalDexFiles() {
239 // Ensure GetRequiredDexChecksum has been run so that
240 // has_original_dex_files_ is initialized. We don't care about the result of
241 // GetRequiredDexChecksum.
242 GetRequiredDexChecksum();
243 return has_original_dex_files_;
244}
245
Richard Uhler66d874d2015-01-15 09:37:19 -0800246const std::string* OatFileAssistant::OdexFileName() {
Richard Uhler743bf362016-04-19 15:39:37 -0700247 return odex_.Filename();
Richard Uhler66d874d2015-01-15 09:37:19 -0800248}
249
250bool OatFileAssistant::OdexFileExists() {
Richard Uhler743bf362016-04-19 15:39:37 -0700251 return odex_.Exists();
Richard Uhler66d874d2015-01-15 09:37:19 -0800252}
253
Richard Uhler95abd042015-03-24 09:51:28 -0700254OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() {
Richard Uhler743bf362016-04-19 15:39:37 -0700255 return odex_.Status();
Richard Uhler66d874d2015-01-15 09:37:19 -0800256}
257
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100258CompilerFilter::Filter OatFileAssistant::OdexFileCompilerFilter() {
Richard Uhler743bf362016-04-19 15:39:37 -0700259 return odex_.CompilerFilter();
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100260}
Richard Uhler4c7f1932016-04-15 15:51:21 -0700261
Richard Uhler66d874d2015-01-15 09:37:19 -0800262const std::string* OatFileAssistant::OatFileName() {
Richard Uhler743bf362016-04-19 15:39:37 -0700263 return oat_.Filename();
Richard Uhler66d874d2015-01-15 09:37:19 -0800264}
265
266bool OatFileAssistant::OatFileExists() {
Richard Uhler743bf362016-04-19 15:39:37 -0700267 return oat_.Exists();
Richard Uhler66d874d2015-01-15 09:37:19 -0800268}
269
Richard Uhler95abd042015-03-24 09:51:28 -0700270OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() {
Richard Uhler743bf362016-04-19 15:39:37 -0700271 return oat_.Status();
Richard Uhler66d874d2015-01-15 09:37:19 -0800272}
273
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100274CompilerFilter::Filter OatFileAssistant::OatFileCompilerFilter() {
Richard Uhler743bf362016-04-19 15:39:37 -0700275 return oat_.CompilerFilter();
Narayan Kamath8943c1d2016-05-02 13:14:48 +0100276}
277
Richard Uhler95abd042015-03-24 09:51:28 -0700278OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800279 // Verify the dex checksum.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700280 // Note: GetOatDexFile will return null if the dex checksum doesn't match
Richard Uhler66d874d2015-01-15 09:37:19 -0800281 // what we provide, which verifies the primary dex checksum for us.
Richard Uhler9a37efc2016-08-05 16:32:55 -0700282 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800283 const uint32_t* dex_checksum_pointer = GetRequiredDexChecksum();
284 const OatFile::OatDexFile* oat_dex_file = file.GetOatDexFile(
Richard Uhler9a37efc2016-08-05 16:32:55 -0700285 dex_location_.c_str(), dex_checksum_pointer, &error_msg);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700286 if (oat_dex_file == nullptr) {
Richard Uhler9a37efc2016-08-05 16:32:55 -0700287 VLOG(oat) << error_msg;
Richard Uhlere8109f72016-04-18 10:40:50 -0700288 return kOatOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800289 }
290
291 // Verify the dex checksums for any secondary multidex files
Andreas Gampe90e34042015-04-27 20:01:52 -0700292 for (size_t i = 1; ; i++) {
Richard Uhler9a37efc2016-08-05 16:32:55 -0700293 std::string secondary_dex_location = DexFile::GetMultiDexLocation(i, dex_location_.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800294 const OatFile::OatDexFile* secondary_oat_dex_file
Richard Uhler9a37efc2016-08-05 16:32:55 -0700295 = file.GetOatDexFile(secondary_dex_location.c_str(), nullptr);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700296 if (secondary_oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800297 // There are no more secondary dex files to check.
298 break;
299 }
300
Richard Uhler66d874d2015-01-15 09:37:19 -0800301 uint32_t expected_secondary_checksum = 0;
302 if (DexFile::GetChecksum(secondary_dex_location.c_str(),
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700303 &expected_secondary_checksum, &error_msg)) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800304 uint32_t actual_secondary_checksum
305 = secondary_oat_dex_file->GetDexFileLocationChecksum();
306 if (expected_secondary_checksum != actual_secondary_checksum) {
307 VLOG(oat) << "Dex checksum does not match for secondary dex: "
308 << secondary_dex_location
309 << ". Expected: " << expected_secondary_checksum
310 << ", Actual: " << actual_secondary_checksum;
Richard Uhlere8109f72016-04-18 10:40:50 -0700311 return kOatOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800312 }
313 } else {
314 // If we can't get the checksum for the secondary location, we assume
315 // the dex checksum is up to date for this and all other secondary dex
316 // files.
317 break;
318 }
319 }
320
Andreas Gampe29d38e72016-03-23 15:31:51 +0000321 CompilerFilter::Filter current_compiler_filter = file.GetCompilerFilter();
David Brazdilce4b0ba2016-01-28 15:05:49 +0000322
Richard Uhler66d874d2015-01-15 09:37:19 -0800323 // Verify the image checksum
Andreas Gampe29d38e72016-03-23 15:31:51 +0000324 if (CompilerFilter::DependsOnImageChecksum(current_compiler_filter)) {
325 const ImageInfo* image_info = GetImageInfo();
326 if (image_info == nullptr) {
327 VLOG(oat) << "No image for oat image checksum to match against.";
Andreas Gampe29d38e72016-03-23 15:31:51 +0000328
Richard Uhler76f5cb62016-04-04 13:30:16 -0700329 if (HasOriginalDexFiles()) {
Richard Uhlere8109f72016-04-18 10:40:50 -0700330 return kOatOutOfDate;
Richard Uhler76f5cb62016-04-04 13:30:16 -0700331 }
332
333 // If there is no original dex file to fall back to, grudgingly accept
334 // the oat file. This could technically lead to crashes, but there's no
335 // way we could find a better oat file to use for this dex location,
336 // and it's better than being stuck in a boot loop with no way out.
337 // The problem will hopefully resolve itself the next time the runtime
338 // starts up.
339 LOG(WARNING) << "Dex location " << dex_location_ << " does not seem to include dex file. "
340 << "Allow oat file use. This is potentially dangerous.";
341 } else if (file.GetOatHeader().GetImageFileLocationOatChecksum()
342 != GetCombinedImageChecksum()) {
Andreas Gampe29d38e72016-03-23 15:31:51 +0000343 VLOG(oat) << "Oat image checksum does not match image checksum.";
Richard Uhlere8109f72016-04-18 10:40:50 -0700344 return kOatOutOfDate;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000345 }
346 } else {
347 VLOG(oat) << "Image checksum test skipped for compiler filter " << current_compiler_filter;
Richard Uhler66d874d2015-01-15 09:37:19 -0800348 }
349
Vladimir Markof6d1e0f2016-05-23 15:32:42 +0100350 if (CompilerFilter::IsBytecodeCompilationEnabled(current_compiler_filter)) {
Andreas Gampe29d38e72016-03-23 15:31:51 +0000351 if (!file.IsPic()) {
352 const ImageInfo* image_info = GetImageInfo();
353 if (image_info == nullptr) {
354 VLOG(oat) << "No image to check oat relocation against.";
Richard Uhlere8109f72016-04-18 10:40:50 -0700355 return kOatNeedsRelocation;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000356 }
Richard Uhlera62d2f02016-03-18 15:05:30 -0700357
Andreas Gampe29d38e72016-03-23 15:31:51 +0000358 // Verify the oat_data_begin recorded for the image in the oat file matches
359 // the actual oat_data_begin for boot.oat in the image.
360 const OatHeader& oat_header = file.GetOatHeader();
361 uintptr_t oat_data_begin = oat_header.GetImageFileLocationOatDataBegin();
362 if (oat_data_begin != image_info->oat_data_begin) {
363 VLOG(oat) << file.GetLocation() <<
364 ": Oat file image oat_data_begin (" << oat_data_begin << ")"
365 << " does not match actual image oat_data_begin ("
366 << image_info->oat_data_begin << ")";
Richard Uhlere8109f72016-04-18 10:40:50 -0700367 return kOatNeedsRelocation;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000368 }
Richard Uhlera62d2f02016-03-18 15:05:30 -0700369
Andreas Gampe29d38e72016-03-23 15:31:51 +0000370 // Verify the oat_patch_delta recorded for the image in the oat file matches
371 // the actual oat_patch_delta for the image.
372 int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
373 if (oat_patch_delta != image_info->patch_delta) {
374 VLOG(oat) << file.GetLocation() <<
375 ": Oat file image patch delta (" << oat_patch_delta << ")"
376 << " does not match actual image patch delta ("
377 << image_info->patch_delta << ")";
Richard Uhlere8109f72016-04-18 10:40:50 -0700378 return kOatNeedsRelocation;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000379 }
380 } else {
381 // Oat files compiled in PIC mode do not require relocation.
382 VLOG(oat) << "Oat relocation test skipped for PIC oat file";
383 }
384 } else {
385 VLOG(oat) << "Oat relocation test skipped for compiler filter " << current_compiler_filter;
Richard Uhler66d874d2015-01-15 09:37:19 -0800386 }
Richard Uhlere8109f72016-04-18 10:40:50 -0700387 return kOatUpToDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800388}
389
Richard Uhler1e860612016-03-30 12:17:55 -0700390OatFileAssistant::ResultOfAttemptToUpdate
391OatFileAssistant::RelocateOatFile(const std::string* input_file, std::string* error_msg) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800392 CHECK(error_msg != nullptr);
393
Richard Uhler95abd042015-03-24 09:51:28 -0700394 if (input_file == nullptr) {
Richard Uhler740eec92015-10-15 15:12:23 -0700395 *error_msg = "Patching of oat file for dex location " + dex_location_
Richard Uhler95abd042015-03-24 09:51:28 -0700396 + " not attempted because the input file name could not be determined.";
Richard Uhler1e860612016-03-30 12:17:55 -0700397 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800398 }
Richard Uhler95abd042015-03-24 09:51:28 -0700399 const std::string& input_file_name = *input_file;
Richard Uhler66d874d2015-01-15 09:37:19 -0800400
Richard Uhler743bf362016-04-19 15:39:37 -0700401 if (oat_.Filename() == nullptr) {
Richard Uhler740eec92015-10-15 15:12:23 -0700402 *error_msg = "Patching of oat file for dex location " + dex_location_
Richard Uhler66d874d2015-01-15 09:37:19 -0800403 + " not attempted because the oat file name could not be determined.";
Richard Uhler1e860612016-03-30 12:17:55 -0700404 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800405 }
Richard Uhler743bf362016-04-19 15:39:37 -0700406 const std::string& oat_file_name = *oat_.Filename();
Richard Uhler66d874d2015-01-15 09:37:19 -0800407
408 const ImageInfo* image_info = GetImageInfo();
409 Runtime* runtime = Runtime::Current();
410 if (image_info == nullptr) {
411 *error_msg = "Patching of oat file " + oat_file_name
412 + " not attempted because no image location was found.";
Richard Uhler1e860612016-03-30 12:17:55 -0700413 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800414 }
415
416 if (!runtime->IsDex2OatEnabled()) {
417 *error_msg = "Patching of oat file " + oat_file_name
418 + " not attempted because dex2oat is disabled";
Richard Uhler1e860612016-03-30 12:17:55 -0700419 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800420 }
421
422 std::vector<std::string> argv;
423 argv.push_back(runtime->GetPatchoatExecutable());
424 argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(isa_)));
Richard Uhler95abd042015-03-24 09:51:28 -0700425 argv.push_back("--input-oat-file=" + input_file_name);
Richard Uhler66d874d2015-01-15 09:37:19 -0800426 argv.push_back("--output-oat-file=" + oat_file_name);
427 argv.push_back("--patched-image-location=" + image_info->location);
428
429 std::string command_line(Join(argv, ' '));
430 if (!Exec(argv, error_msg)) {
431 // Manually delete the file. This ensures there is no garbage left over if
432 // the process unexpectedly died.
Vladimir Marko66fdcbd2016-04-05 14:19:08 +0100433 unlink(oat_file_name.c_str());
Richard Uhler1e860612016-03-30 12:17:55 -0700434 return kUpdateFailed;
Richard Uhler66d874d2015-01-15 09:37:19 -0800435 }
436
437 // Mark that the oat file has changed and we should try to reload.
Richard Uhler743bf362016-04-19 15:39:37 -0700438 oat_.Reset();
Richard Uhler1e860612016-03-30 12:17:55 -0700439 return kUpdateSucceeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800440}
441
Richard Uhler1e860612016-03-30 12:17:55 -0700442OatFileAssistant::ResultOfAttemptToUpdate
Richard Uhlerf4b34872016-04-13 11:03:46 -0700443OatFileAssistant::GenerateOatFile(std::string* error_msg) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800444 CHECK(error_msg != nullptr);
445
Richard Uhler8327cf72015-10-13 16:34:59 -0700446 Runtime* runtime = Runtime::Current();
447 if (!runtime->IsDex2OatEnabled()) {
448 *error_msg = "Generation of oat file for dex location " + dex_location_
449 + " not attempted because dex2oat is disabled.";
Richard Uhler1e860612016-03-30 12:17:55 -0700450 return kUpdateNotAttempted;
Richard Uhler8327cf72015-10-13 16:34:59 -0700451 }
452
Richard Uhler743bf362016-04-19 15:39:37 -0700453 if (oat_.Filename() == nullptr) {
Richard Uhler740eec92015-10-15 15:12:23 -0700454 *error_msg = "Generation of oat file for dex location " + dex_location_
Richard Uhler66d874d2015-01-15 09:37:19 -0800455 + " not attempted because the oat file name could not be determined.";
Richard Uhler1e860612016-03-30 12:17:55 -0700456 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800457 }
Richard Uhler743bf362016-04-19 15:39:37 -0700458 const std::string& oat_file_name = *oat_.Filename();
David Brazdil7b49e6c2016-09-01 11:06:18 +0100459 const std::string& vdex_file_name = ReplaceFileExtension(oat_file_name, "vdex");
Richard Uhler66d874d2015-01-15 09:37:19 -0800460
Richard Uhler66d874d2015-01-15 09:37:19 -0800461 // dex2oat ignores missing dex files and doesn't report an error.
462 // Check explicitly here so we can detect the error properly.
463 // TODO: Why does dex2oat behave that way?
Richard Uhler740eec92015-10-15 15:12:23 -0700464 if (!OS::FileExists(dex_location_.c_str())) {
465 *error_msg = "Dex location " + dex_location_ + " does not exists.";
Richard Uhler1e860612016-03-30 12:17:55 -0700466 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800467 }
468
David Brazdil7b49e6c2016-09-01 11:06:18 +0100469 std::unique_ptr<File> vdex_file(OS::CreateEmptyFile(vdex_file_name.c_str()));
470 if (vdex_file.get() == nullptr) {
471 *error_msg = "Generation of oat file " + oat_file_name
472 + " not attempted because the vdex file " + vdex_file_name
473 + " could not be opened.";
474 return kUpdateNotAttempted;
475 }
476
477 if (fchmod(vdex_file->Fd(), 0644) != 0) {
478 *error_msg = "Generation of oat file " + oat_file_name
479 + " not attempted because the vdex file " + vdex_file_name
480 + " could not be made world readable.";
481 return kUpdateNotAttempted;
482 }
483
484 std::unique_ptr<File> oat_file(OS::CreateEmptyFile(oat_file_name.c_str()));
Richard Uhler8327cf72015-10-13 16:34:59 -0700485 if (oat_file.get() == nullptr) {
486 *error_msg = "Generation of oat file " + oat_file_name
487 + " not attempted because the oat file could not be created.";
Richard Uhler1e860612016-03-30 12:17:55 -0700488 return kUpdateNotAttempted;
Richard Uhler8327cf72015-10-13 16:34:59 -0700489 }
490
491 if (fchmod(oat_file->Fd(), 0644) != 0) {
492 *error_msg = "Generation of oat file " + oat_file_name
493 + " not attempted because the oat file could not be made world readable.";
494 oat_file->Erase();
Richard Uhler1e860612016-03-30 12:17:55 -0700495 return kUpdateNotAttempted;
Richard Uhler8327cf72015-10-13 16:34:59 -0700496 }
497
498 std::vector<std::string> args;
499 args.push_back("--dex-file=" + dex_location_);
Nicolas Geoffraya6a448a2016-11-10 10:49:40 +0000500 args.push_back("--output-vdex-fd=" + std::to_string(vdex_file->Fd()));
Richard Uhler8327cf72015-10-13 16:34:59 -0700501 args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
502 args.push_back("--oat-location=" + oat_file_name);
503
Richard Uhler66d874d2015-01-15 09:37:19 -0800504 if (!Dex2Oat(args, error_msg)) {
David Brazdil7b49e6c2016-09-01 11:06:18 +0100505 // Manually delete the oat and vdex files. This ensures there is no garbage
506 // left over if the process unexpectedly died.
507 vdex_file->Erase();
508 unlink(vdex_file_name.c_str());
Richard Uhler8327cf72015-10-13 16:34:59 -0700509 oat_file->Erase();
Vladimir Marko66fdcbd2016-04-05 14:19:08 +0100510 unlink(oat_file_name.c_str());
Richard Uhler1e860612016-03-30 12:17:55 -0700511 return kUpdateFailed;
Richard Uhler8327cf72015-10-13 16:34:59 -0700512 }
513
David Brazdil7b49e6c2016-09-01 11:06:18 +0100514 if (vdex_file->FlushCloseOrErase() != 0) {
515 *error_msg = "Unable to close vdex file " + vdex_file_name;
516 unlink(vdex_file_name.c_str());
517 return kUpdateFailed;
518 }
519
Richard Uhler8327cf72015-10-13 16:34:59 -0700520 if (oat_file->FlushCloseOrErase() != 0) {
521 *error_msg = "Unable to close oat file " + oat_file_name;
Vladimir Marko66fdcbd2016-04-05 14:19:08 +0100522 unlink(oat_file_name.c_str());
Richard Uhler1e860612016-03-30 12:17:55 -0700523 return kUpdateFailed;
Richard Uhler66d874d2015-01-15 09:37:19 -0800524 }
525
526 // Mark that the oat file has changed and we should try to reload.
Richard Uhler743bf362016-04-19 15:39:37 -0700527 oat_.Reset();
Richard Uhler1e860612016-03-30 12:17:55 -0700528 return kUpdateSucceeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800529}
530
531bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args,
532 std::string* error_msg) {
533 Runtime* runtime = Runtime::Current();
534 std::string image_location = ImageLocation();
535 if (image_location.empty()) {
536 *error_msg = "No image location found for Dex2Oat.";
537 return false;
538 }
539
540 std::vector<std::string> argv;
541 argv.push_back(runtime->GetCompilerExecutable());
542 argv.push_back("--runtime-arg");
543 argv.push_back("-classpath");
544 argv.push_back("--runtime-arg");
Jeff Haof0192c82016-03-28 20:39:50 -0700545 std::string class_path = runtime->GetClassPathString();
546 if (class_path == "") {
547 class_path = OatFile::kSpecialSharedLibrary;
548 }
549 argv.push_back(class_path);
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +0100550 if (runtime->IsDebuggable()) {
Sebastien Hertz0de11332015-05-13 12:14:05 +0200551 argv.push_back("--debuggable");
552 }
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700553 runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
Richard Uhler66d874d2015-01-15 09:37:19 -0800554
555 if (!runtime->IsVerificationEnabled()) {
556 argv.push_back("--compiler-filter=verify-none");
557 }
558
559 if (runtime->MustRelocateIfPossible()) {
560 argv.push_back("--runtime-arg");
561 argv.push_back("-Xrelocate");
562 } else {
563 argv.push_back("--runtime-arg");
564 argv.push_back("-Xnorelocate");
565 }
566
567 if (!kIsTargetBuild) {
568 argv.push_back("--host");
569 }
570
571 argv.push_back("--boot-image=" + image_location);
572
573 std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
574 argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
575
576 argv.insert(argv.end(), args.begin(), args.end());
577
578 std::string command_line(Join(argv, ' '));
579 return Exec(argv, error_msg);
580}
581
Richard Uhlerb81881d2016-04-19 13:08:04 -0700582bool OatFileAssistant::DexLocationToOdexFilename(const std::string& location,
583 InstructionSet isa,
584 std::string* odex_filename,
585 std::string* error_msg) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800586 CHECK(odex_filename != nullptr);
587 CHECK(error_msg != nullptr);
588
589 // The odex file name is formed by replacing the dex_location extension with
Richard Uhler63434112015-03-16 14:32:16 -0700590 // .odex and inserting an oat/<isa> directory. For example:
Richard Uhler66d874d2015-01-15 09:37:19 -0800591 // location = /foo/bar/baz.jar
Richard Uhler63434112015-03-16 14:32:16 -0700592 // odex_location = /foo/bar/oat/<isa>/baz.odex
Richard Uhler66d874d2015-01-15 09:37:19 -0800593
Richard Uhler63434112015-03-16 14:32:16 -0700594 // Find the directory portion of the dex location and add the oat/<isa>
595 // directory.
Richard Uhler66d874d2015-01-15 09:37:19 -0800596 size_t pos = location.rfind('/');
597 if (pos == std::string::npos) {
598 *error_msg = "Dex location " + location + " has no directory.";
599 return false;
600 }
601 std::string dir = location.substr(0, pos+1);
Richard Uhler63434112015-03-16 14:32:16 -0700602 dir += "oat/" + std::string(GetInstructionSetString(isa));
Richard Uhler66d874d2015-01-15 09:37:19 -0800603
604 // Find the file portion of the dex location.
605 std::string file;
606 if (pos == std::string::npos) {
607 file = location;
608 } else {
609 file = location.substr(pos+1);
610 }
611
612 // Get the base part of the file without the extension.
613 pos = file.rfind('.');
614 if (pos == std::string::npos) {
615 *error_msg = "Dex location " + location + " has no extension.";
616 return false;
617 }
618 std::string base = file.substr(0, pos);
619
620 *odex_filename = dir + "/" + base + ".odex";
621 return true;
622}
623
Richard Uhlerb81881d2016-04-19 13:08:04 -0700624bool OatFileAssistant::DexLocationToOatFilename(const std::string& location,
625 InstructionSet isa,
626 std::string* oat_filename,
627 std::string* error_msg) {
628 CHECK(oat_filename != nullptr);
629 CHECK(error_msg != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800630
Richard Uhler55b58b62016-08-12 09:05:13 -0700631 std::string cache_dir = GetDalvikCache(GetInstructionSetString(isa));
632 if (cache_dir.empty()) {
633 *error_msg = "Dalvik cache directory does not exist";
634 return false;
635 }
Richard Uhlerb81881d2016-04-19 13:08:04 -0700636
637 // TODO: The oat file assistant should be the definitive place for
638 // determining the oat file name from the dex location, not
639 // GetDalvikCacheFilename.
Richard Uhlerb81881d2016-04-19 13:08:04 -0700640 return GetDalvikCacheFilename(location.c_str(), cache_dir.c_str(), oat_filename, error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800641}
642
Richard Uhler66d874d2015-01-15 09:37:19 -0800643std::string OatFileAssistant::ImageLocation() {
644 Runtime* runtime = Runtime::Current();
Andreas Gampe8994a042015-12-30 19:03:17 +0000645 const std::vector<gc::space::ImageSpace*>& image_spaces =
646 runtime->GetHeap()->GetBootImageSpaces();
647 if (image_spaces.empty()) {
648 return "";
649 }
650 return image_spaces[0]->GetImageLocation();
Richard Uhler66d874d2015-01-15 09:37:19 -0800651}
652
653const uint32_t* OatFileAssistant::GetRequiredDexChecksum() {
Richard Uhler9b994ea2015-06-24 08:44:19 -0700654 if (!required_dex_checksum_attempted_) {
655 required_dex_checksum_attempted_ = true;
656 required_dex_checksum_found_ = false;
Richard Uhler66d874d2015-01-15 09:37:19 -0800657 std::string error_msg;
Richard Uhler740eec92015-10-15 15:12:23 -0700658 if (DexFile::GetChecksum(dex_location_.c_str(), &cached_required_dex_checksum_, &error_msg)) {
Richard Uhler9b994ea2015-06-24 08:44:19 -0700659 required_dex_checksum_found_ = true;
660 has_original_dex_files_ = true;
Richard Uhler66d874d2015-01-15 09:37:19 -0800661 } else {
662 // This can happen if the original dex file has been stripped from the
663 // apk.
664 VLOG(oat) << "OatFileAssistant: " << error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700665 has_original_dex_files_ = false;
Richard Uhler66d874d2015-01-15 09:37:19 -0800666
667 // Get the checksum from the odex if we can.
Richard Uhler743bf362016-04-19 15:39:37 -0700668 const OatFile* odex_file = odex_.GetFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800669 if (odex_file != nullptr) {
Richard Uhler9a37efc2016-08-05 16:32:55 -0700670 const OatFile::OatDexFile* odex_dex_file
671 = odex_file->GetOatDexFile(dex_location_.c_str(), nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800672 if (odex_dex_file != nullptr) {
Richard Uhler9b994ea2015-06-24 08:44:19 -0700673 cached_required_dex_checksum_ = odex_dex_file->GetDexFileLocationChecksum();
674 required_dex_checksum_found_ = true;
Richard Uhler66d874d2015-01-15 09:37:19 -0800675 }
676 }
677 }
678 }
Richard Uhler9b994ea2015-06-24 08:44:19 -0700679 return required_dex_checksum_found_ ? &cached_required_dex_checksum_ : nullptr;
Richard Uhler66d874d2015-01-15 09:37:19 -0800680}
681
Richard Uhler66d874d2015-01-15 09:37:19 -0800682const OatFileAssistant::ImageInfo* OatFileAssistant::GetImageInfo() {
683 if (!image_info_load_attempted_) {
684 image_info_load_attempted_ = true;
685
686 Runtime* runtime = Runtime::Current();
Jeff Haodcdc85b2015-12-04 14:06:18 -0800687 std::vector<gc::space::ImageSpace*> image_spaces = runtime->GetHeap()->GetBootImageSpaces();
688 if (!image_spaces.empty()) {
Jeff Haodcdc85b2015-12-04 14:06:18 -0800689 cached_image_info_.location = image_spaces[0]->GetImageLocation();
Richard Uhler66d874d2015-01-15 09:37:19 -0800690
691 if (isa_ == kRuntimeISA) {
Jeff Haodcdc85b2015-12-04 14:06:18 -0800692 const ImageHeader& image_header = image_spaces[0]->GetImageHeader();
Richard Uhler66d874d2015-01-15 09:37:19 -0800693 cached_image_info_.oat_checksum = image_header.GetOatChecksum();
Mathieu Chartier073b16c2015-11-10 14:13:23 -0800694 cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(
695 image_header.GetOatDataBegin());
Richard Uhler66d874d2015-01-15 09:37:19 -0800696 cached_image_info_.patch_delta = image_header.GetPatchDelta();
697 } else {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700698 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800699 std::unique_ptr<ImageHeader> image_header(
Andreas Gampea463b6a2016-08-12 21:53:32 -0700700 gc::space::ImageSpace::ReadImageHeader(cached_image_info_.location.c_str(),
701 isa_,
702 &error_msg));
703 CHECK(image_header != nullptr) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800704 cached_image_info_.oat_checksum = image_header->GetOatChecksum();
Mathieu Chartier073b16c2015-11-10 14:13:23 -0800705 cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(
706 image_header->GetOatDataBegin());
Richard Uhler66d874d2015-01-15 09:37:19 -0800707 cached_image_info_.patch_delta = image_header->GetPatchDelta();
708 }
709 }
Jeff Haodcdc85b2015-12-04 14:06:18 -0800710 image_info_load_succeeded_ = (!image_spaces.empty());
Jeff Haob11ffb72016-04-07 15:40:54 -0700711
Jeff Haofd336c32016-04-07 19:46:31 -0700712 combined_image_checksum_ = CalculateCombinedImageChecksum(isa_);
Richard Uhler66d874d2015-01-15 09:37:19 -0800713 }
714 return image_info_load_succeeded_ ? &cached_image_info_ : nullptr;
715}
716
Jeff Haob11ffb72016-04-07 15:40:54 -0700717// TODO: Use something better than xor.
Jeff Haofd336c32016-04-07 19:46:31 -0700718uint32_t OatFileAssistant::CalculateCombinedImageChecksum(InstructionSet isa) {
Jeff Haob11ffb72016-04-07 15:40:54 -0700719 uint32_t checksum = 0;
720 std::vector<gc::space::ImageSpace*> image_spaces =
721 Runtime::Current()->GetHeap()->GetBootImageSpaces();
Jeff Haofd336c32016-04-07 19:46:31 -0700722 if (isa == kRuntimeISA) {
723 for (gc::space::ImageSpace* image_space : image_spaces) {
724 checksum ^= image_space->GetImageHeader().GetOatChecksum();
725 }
726 } else {
727 for (gc::space::ImageSpace* image_space : image_spaces) {
728 std::string location = image_space->GetImageLocation();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700729 std::string error_msg;
Jeff Haofd336c32016-04-07 19:46:31 -0700730 std::unique_ptr<ImageHeader> image_header(
Andreas Gampea463b6a2016-08-12 21:53:32 -0700731 gc::space::ImageSpace::ReadImageHeader(location.c_str(), isa, &error_msg));
732 CHECK(image_header != nullptr) << error_msg;
Jeff Haofd336c32016-04-07 19:46:31 -0700733 checksum ^= image_header->GetOatChecksum();
734 }
Jeff Haob11ffb72016-04-07 15:40:54 -0700735 }
736 return checksum;
737}
738
739uint32_t OatFileAssistant::GetCombinedImageChecksum() {
740 if (!image_info_load_attempted_) {
741 GetImageInfo();
742 }
743 return combined_image_checksum_;
744}
745
Andreas Gampea463b6a2016-08-12 21:53:32 -0700746std::unique_ptr<gc::space::ImageSpace> OatFileAssistant::OpenImageSpace(const OatFile* oat_file) {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800747 DCHECK(oat_file != nullptr);
David Brazdil7b49e6c2016-09-01 11:06:18 +0100748 std::string art_file = ReplaceFileExtension(oat_file->GetLocation(), "art");
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800749 if (art_file.empty()) {
750 return nullptr;
751 }
752 std::string error_msg;
753 ScopedObjectAccess soa(Thread::Current());
Andreas Gampea463b6a2016-08-12 21:53:32 -0700754 std::unique_ptr<gc::space::ImageSpace> ret =
755 gc::space::ImageSpace::CreateFromAppImage(art_file.c_str(), oat_file, &error_msg);
Mathieu Chartiere778fc72016-01-25 20:11:28 -0800756 if (ret == nullptr && (VLOG_IS_ON(image) || OS::FileExists(art_file.c_str()))) {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800757 LOG(INFO) << "Failed to open app image " << art_file.c_str() << " " << error_msg;
758 }
759 return ret;
760}
761
Richard Uhler743bf362016-04-19 15:39:37 -0700762OatFileAssistant::OatFileInfo::OatFileInfo(OatFileAssistant* oat_file_assistant)
763 : oat_file_assistant_(oat_file_assistant)
764{}
765
766const std::string* OatFileAssistant::OatFileInfo::Filename() {
767 return filename_provided_ ? &filename_ : nullptr;
768}
769
770bool OatFileAssistant::OatFileInfo::Exists() {
771 return GetFile() != nullptr;
772}
773
774OatFileAssistant::OatStatus OatFileAssistant::OatFileInfo::Status() {
775 if (!status_attempted_) {
776 status_attempted_ = true;
777 const OatFile* file = GetFile();
778 if (file == nullptr) {
779 status_ = kOatOutOfDate;
780 } else {
781 status_ = oat_file_assistant_->GivenOatFileStatus(*file);
Richard Uhler9a37efc2016-08-05 16:32:55 -0700782 VLOG(oat) << file->GetLocation() << " is " << status_
783 << " with filter " << file->GetCompilerFilter();
Richard Uhler743bf362016-04-19 15:39:37 -0700784 }
785 }
786 return status_;
787}
788
Richard Uhler743bf362016-04-19 15:39:37 -0700789CompilerFilter::Filter OatFileAssistant::OatFileInfo::CompilerFilter() {
790 const OatFile* file = GetFile();
791 CHECK(file != nullptr);
792 return file->GetCompilerFilter();
793}
794
Richard Uhler70a84262016-11-08 16:51:51 +0000795OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded(
796 CompilerFilter::Filter target, bool profile_changed) {
797 bool compilation_desired = CompilerFilter::IsBytecodeCompilationEnabled(target);
798
Richard Uhler3e580bc2016-11-08 16:23:07 +0000799 if (CompilerFilterIsOkay(target, profile_changed)) {
800 if (Status() == kOatUpToDate) {
801 // The oat file is in good shape as is.
802 return kNoDexOptNeeded;
803 }
804
805 if (Status() == kOatNeedsRelocation) {
806 if (!compilation_desired) {
807 // If no compilation is desired, then it doesn't matter if the oat
808 // file needs relocation. It's in good shape as is.
Richard Uhler70a84262016-11-08 16:51:51 +0000809 return kNoDexOptNeeded;
810 }
Richard Uhler3e580bc2016-11-08 16:23:07 +0000811
812 if (compilation_desired && HasPatchInfo()) {
813 // Relocate if we can.
814 return kPatchOatNeeded;
Richard Uhler70a84262016-11-08 16:51:51 +0000815 }
816 }
817 }
818
Richard Uhler70a84262016-11-08 16:51:51 +0000819 // We can only run dex2oat if there are original dex files.
820 return oat_file_assistant_->HasOriginalDexFiles() ? kDex2OatNeeded : kNoDexOptNeeded;
821}
822
Richard Uhler743bf362016-04-19 15:39:37 -0700823const OatFile* OatFileAssistant::OatFileInfo::GetFile() {
824 CHECK(!file_released_) << "GetFile called after oat file released.";
825 if (!load_attempted_) {
826 load_attempted_ = true;
827 if (filename_provided_) {
828 std::string error_msg;
829 file_.reset(OatFile::Open(filename_.c_str(),
830 filename_.c_str(),
831 nullptr,
832 nullptr,
833 oat_file_assistant_->load_executable_,
834 /*low_4gb*/false,
835 oat_file_assistant_->dex_location_.c_str(),
836 &error_msg));
837 if (file_.get() == nullptr) {
838 VLOG(oat) << "OatFileAssistant test for existing oat file "
839 << filename_ << ": " << error_msg;
840 }
841 }
842 }
843 return file_.get();
844}
845
846bool OatFileAssistant::OatFileInfo::CompilerFilterIsOkay(
847 CompilerFilter::Filter target, bool profile_changed) {
848 const OatFile* file = GetFile();
849 if (file == nullptr) {
850 return false;
851 }
852
853 CompilerFilter::Filter current = file->GetCompilerFilter();
854 if (profile_changed && CompilerFilter::DependsOnProfile(current)) {
855 VLOG(oat) << "Compiler filter not okay because Profile changed";
856 return false;
857 }
858 return CompilerFilter::IsAsGoodAs(current, target);
859}
860
861bool OatFileAssistant::OatFileInfo::IsExecutable() {
862 const OatFile* file = GetFile();
863 return (file != nullptr && file->IsExecutable());
864}
865
866bool OatFileAssistant::OatFileInfo::HasPatchInfo() {
867 const OatFile* file = GetFile();
868 return (file != nullptr && file->HasPatchInfo());
869}
870
871void OatFileAssistant::OatFileInfo::Reset() {
872 load_attempted_ = false;
873 file_.reset();
874 status_attempted_ = false;
875}
876
877void OatFileAssistant::OatFileInfo::Reset(const std::string& filename) {
878 filename_provided_ = true;
879 filename_ = filename;
880 Reset();
881}
882
883std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFile() {
884 file_released_ = true;
885 return std::move(file_);
886}
887
Richard Uhler70a84262016-11-08 16:51:51 +0000888std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFileForUse() {
Richard Uhler3e580bc2016-11-08 16:23:07 +0000889 if (Status() == kOatUpToDate) {
Richard Uhler70a84262016-11-08 16:51:51 +0000890 return ReleaseFile();
891 }
892
893 VLOG(oat) << "Oat File Assistant: No relocated oat file found,"
894 << " attempting to fall back to interpreting oat file instead.";
895
Richard Uhler3e580bc2016-11-08 16:23:07 +0000896 if (Status() == kOatNeedsRelocation && !IsExecutable()) {
Richard Uhler70a84262016-11-08 16:51:51 +0000897 return ReleaseFile();
898 }
899
Richard Uhler3e580bc2016-11-08 16:23:07 +0000900 if (Status() == kOatNeedsRelocation) {
Richard Uhler70a84262016-11-08 16:51:51 +0000901 // We are loading an oat file for runtime use that needs relocation.
902 // Reload the file non-executable to ensure that we interpret out of the
903 // dex code in the oat file rather than trying to execute the unrelocated
904 // compiled code.
905 oat_file_assistant_->load_executable_ = false;
906 Reset();
Richard Uhler3e580bc2016-11-08 16:23:07 +0000907 if (Status() != kOatOutOfDate) {
Richard Uhler70a84262016-11-08 16:51:51 +0000908 CHECK(!IsExecutable());
909 return ReleaseFile();
910 }
911 }
912 return std::unique_ptr<OatFile>();
913}
Richard Uhler66d874d2015-01-15 09:37:19 -0800914} // namespace art
915