blob: 6a62a166a31f60eab97ecd0b6cdebfada88c9680 [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 Uhler46cc64f2016-11-14 14:53:55 +000019#include <sstream>
20
Richard Uhler66d874d2015-01-15 09:37:19 -080021#include <sys/stat.h>
Richard Uhler66d874d2015-01-15 09:37:19 -080022#include "base/logging.h"
23#include "base/stringprintf.h"
Narayan Kamath8943c1d2016-05-02 13:14:48 +010024#include "compiler_filter.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080025#include "class_linker.h"
26#include "gc/heap.h"
27#include "gc/space/image_space.h"
28#include "image.h"
29#include "oat.h"
30#include "os.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080031#include "runtime.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070032#include "scoped_thread_state_change-inl.h"
Richard Uhler66d874d2015-01-15 09:37:19 -080033#include "utils.h"
34
35namespace art {
36
Narayan Kamath8943c1d2016-05-02 13:14:48 +010037std::ostream& operator << (std::ostream& stream, const OatFileAssistant::OatStatus status) {
38 switch (status) {
Richard Uhler03bc6592016-11-22 09:42:04 +000039 case OatFileAssistant::kOatCannotOpen:
40 stream << "kOatCannotOpen";
41 break;
42 case OatFileAssistant::kOatDexOutOfDate:
43 stream << "kOatDexOutOfDate";
44 break;
45 case OatFileAssistant::kOatBootImageOutOfDate:
46 stream << "kOatBootImageOutOfDate";
47 break;
48 case OatFileAssistant::kOatRelocationOutOfDate:
49 stream << "kOatRelocationOutOfDate";
Narayan Kamath8943c1d2016-05-02 13:14:48 +010050 break;
51 case OatFileAssistant::kOatUpToDate:
52 stream << "kOatUpToDate";
53 break;
Narayan Kamath8943c1d2016-05-02 13:14:48 +010054 default:
55 UNREACHABLE();
56 }
57
58 return stream;
59}
60
Richard Uhler66d874d2015-01-15 09:37:19 -080061OatFileAssistant::OatFileAssistant(const char* dex_location,
62 const InstructionSet isa,
63 bool load_executable)
Richard Uhlerd1472a22016-04-15 15:18:56 -070064 : OatFileAssistant(dex_location, nullptr, isa, load_executable)
Calin Juravleb077e152016-02-18 18:47:37 +000065{ }
Richard Uhler66d874d2015-01-15 09:37:19 -080066
67OatFileAssistant::OatFileAssistant(const char* dex_location,
68 const char* oat_location,
69 const InstructionSet isa,
70 bool load_executable)
Richard Uhler88bc6732016-11-14 14:38:03 +000071 : isa_(isa),
72 load_executable_(load_executable),
73 odex_(this, /*is_oat_location*/ false),
74 oat_(this, /*is_oat_location*/ true) {
Richard Uhler740eec92015-10-15 15:12:23 -070075 CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location";
76 dex_location_.assign(dex_location);
77
Richard Uhler66d874d2015-01-15 09:37:19 -080078 if (load_executable_ && isa != kRuntimeISA) {
79 LOG(WARNING) << "OatFileAssistant: Load executable specified, "
80 << "but isa is not kRuntimeISA. Will not attempt to load executable.";
81 load_executable_ = false;
82 }
83
Richard Uhler743bf362016-04-19 15:39:37 -070084 // Get the odex filename.
Richard Uhlerd684f522016-04-19 13:24:41 -070085 std::string error_msg;
Richard Uhler743bf362016-04-19 15:39:37 -070086 std::string odex_file_name;
87 if (DexLocationToOdexFilename(dex_location_, isa_, &odex_file_name, &error_msg)) {
88 odex_.Reset(odex_file_name);
89 } else {
Richard Uhlerd684f522016-04-19 13:24:41 -070090 LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
91 }
92
Richard Uhler743bf362016-04-19 15:39:37 -070093 // Get the oat filename.
Richard Uhler66d874d2015-01-15 09:37:19 -080094 if (oat_location != nullptr) {
Richard Uhler743bf362016-04-19 15:39:37 -070095 oat_.Reset(oat_location);
Richard Uhlerd684f522016-04-19 13:24:41 -070096 } else {
Richard Uhler743bf362016-04-19 15:39:37 -070097 std::string oat_file_name;
98 if (DexLocationToOatFilename(dex_location_, isa_, &oat_file_name, &error_msg)) {
99 oat_.Reset(oat_file_name);
100 } else {
Richard Uhlerd684f522016-04-19 13:24:41 -0700101 LOG(WARNING) << "Failed to determine oat file name for dex location "
102 << dex_location_ << ": " << error_msg;
103 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800104 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800105}
106
107OatFileAssistant::~OatFileAssistant() {
108 // Clean up the lock file.
Richard Uhler581f4e92015-05-07 10:19:35 -0700109 if (flock_.HasFile()) {
Vladimir Marko66fdcbd2016-04-05 14:19:08 +0100110 unlink(flock_.GetFile()->GetPath().c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800111 }
112}
113
114bool OatFileAssistant::IsInBootClassPath() {
115 // Note: We check the current boot class path, regardless of the ISA
116 // specified by the user. This is okay, because the boot class path should
117 // be the same for all ISAs.
118 // TODO: Can we verify the boot class path is the same for all ISAs?
119 Runtime* runtime = Runtime::Current();
120 ClassLinker* class_linker = runtime->GetClassLinker();
121 const auto& boot_class_path = class_linker->GetBootClassPath();
122 for (size_t i = 0; i < boot_class_path.size(); i++) {
Richard Uhler740eec92015-10-15 15:12:23 -0700123 if (boot_class_path[i]->GetLocation() == dex_location_) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800124 VLOG(oat) << "Dex location " << dex_location_ << " is in boot class path";
125 return true;
126 }
127 }
128 return false;
129}
130
131bool OatFileAssistant::Lock(std::string* error_msg) {
132 CHECK(error_msg != nullptr);
Richard Uhler581f4e92015-05-07 10:19:35 -0700133 CHECK(!flock_.HasFile()) << "OatFileAssistant::Lock already acquired";
Richard Uhler66d874d2015-01-15 09:37:19 -0800134
Richard Uhler743bf362016-04-19 15:39:37 -0700135 const std::string* oat_file_name = oat_.Filename();
136 if (oat_file_name == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800137 *error_msg = "Failed to determine lock file";
138 return false;
139 }
Richard Uhler743bf362016-04-19 15:39:37 -0700140 std::string lock_file_name = *oat_file_name + ".flock";
Richard Uhler66d874d2015-01-15 09:37:19 -0800141
Richard Uhler581f4e92015-05-07 10:19:35 -0700142 if (!flock_.Init(lock_file_name.c_str(), error_msg)) {
Vladimir Marko66fdcbd2016-04-05 14:19:08 +0100143 unlink(lock_file_name.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800144 return false;
145 }
146 return true;
147}
148
Richard Uhler7225a8d2016-11-22 10:12:03 +0000149int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target, bool profile_changed) {
Richard Uhler88bc6732016-11-14 14:38:03 +0000150 OatFileInfo& info = GetBestInfo();
151 DexOptNeeded dexopt_needed = info.GetDexOptNeeded(target, profile_changed);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000152 if (info.IsOatLocation() || dexopt_needed == kDex2OatFromScratch) {
153 return dexopt_needed;
Richard Uhler66d874d2015-01-15 09:37:19 -0800154 }
Richard Uhler7225a8d2016-11-22 10:12:03 +0000155 return -dexopt_needed;
Richard Uhler66d874d2015-01-15 09:37:19 -0800156}
157
Richard Uhlerf4b34872016-04-13 11:03:46 -0700158// Figure out the currently specified compile filter option in the runtime.
159// Returns true on success, false if the compiler filter is invalid, in which
160// case error_msg describes the problem.
161static bool GetRuntimeCompilerFilterOption(CompilerFilter::Filter* filter,
162 std::string* error_msg) {
163 CHECK(filter != nullptr);
164 CHECK(error_msg != nullptr);
165
166 *filter = CompilerFilter::kDefaultCompilerFilter;
167 for (StringPiece option : Runtime::Current()->GetCompilerOptions()) {
168 if (option.starts_with("--compiler-filter=")) {
169 const char* compiler_filter_string = option.substr(strlen("--compiler-filter=")).data();
170 if (!CompilerFilter::ParseCompilerFilter(compiler_filter_string, filter)) {
171 *error_msg = std::string("Unknown --compiler-filter value: ")
172 + std::string(compiler_filter_string);
173 return false;
174 }
175 }
176 }
177 return true;
178}
179
Richard Uhler01be6812016-05-17 10:34:52 -0700180bool OatFileAssistant::IsUpToDate() {
Richard Uhler88bc6732016-11-14 14:38:03 +0000181 return GetBestInfo().Status() == kOatUpToDate;
Richard Uhler01be6812016-05-17 10:34:52 -0700182}
183
Richard Uhler1e860612016-03-30 12:17:55 -0700184OatFileAssistant::ResultOfAttemptToUpdate
Richard Uhlerd1472a22016-04-15 15:18:56 -0700185OatFileAssistant::MakeUpToDate(bool profile_changed, std::string* error_msg) {
Richard Uhlerf4b34872016-04-13 11:03:46 -0700186 CompilerFilter::Filter target;
187 if (!GetRuntimeCompilerFilterOption(&target, error_msg)) {
188 return kUpdateNotAttempted;
189 }
190
Richard Uhler88bc6732016-11-14 14:38:03 +0000191 OatFileInfo& info = GetBestInfo();
192 switch (info.GetDexOptNeeded(target, profile_changed)) {
Richard Uhler7225a8d2016-11-22 10:12:03 +0000193 case kNoDexOptNeeded:
194 return kUpdateSucceeded;
Richard Uhler88bc6732016-11-14 14:38:03 +0000195
Richard Uhler7225a8d2016-11-22 10:12:03 +0000196 // TODO: For now, don't bother with all the different ways we can call
197 // dex2oat to generate the oat file. Always generate the oat file as if it
198 // were kDex2OatFromScratch.
199 case kDex2OatFromScratch:
200 case kDex2OatForBootImage:
201 case kDex2OatForRelocation:
202 case kDex2OatForFilter:
203 return GenerateOatFile(error_msg);
204
205 case kPatchoatForRelocation: {
206 return RelocateOatFile(info.Filename(), error_msg);
207 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800208 }
209 UNREACHABLE();
210}
211
212std::unique_ptr<OatFile> OatFileAssistant::GetBestOatFile() {
Richard Uhler88bc6732016-11-14 14:38:03 +0000213 return GetBestInfo().ReleaseFileForUse();
Richard Uhler66d874d2015-01-15 09:37:19 -0800214}
215
Richard Uhler46cc64f2016-11-14 14:53:55 +0000216std::string OatFileAssistant::GetStatusDump() {
217 std::ostringstream status;
218 bool oat_file_exists = false;
219 bool odex_file_exists = false;
Richard Uhler03bc6592016-11-22 09:42:04 +0000220 if (oat_.Status() != kOatCannotOpen) {
221 // If we can open the file, neither Filename nor GetFile should return null.
222 CHECK(oat_.Filename() != nullptr);
223 CHECK(oat_.GetFile() != nullptr);
224
Richard Uhler46cc64f2016-11-14 14:53:55 +0000225 oat_file_exists = true;
226 status << *oat_.Filename() << " [compilation_filter=";
Richard Uhler03bc6592016-11-22 09:42:04 +0000227 status << CompilerFilter::NameOfFilter(oat_.GetFile()->GetCompilerFilter());
Richard Uhler46cc64f2016-11-14 14:53:55 +0000228 status << ", status=" << oat_.Status();
229 }
230
Richard Uhler03bc6592016-11-22 09:42:04 +0000231 if (odex_.Status() != kOatCannotOpen) {
232 // If we can open the file, neither Filename nor GetFile should return null.
233 CHECK(odex_.Filename() != nullptr);
234 CHECK(odex_.GetFile() != nullptr);
235
Richard Uhler46cc64f2016-11-14 14:53:55 +0000236 odex_file_exists = true;
237 if (oat_file_exists) {
238 status << "] ";
239 }
240 status << *odex_.Filename() << " [compilation_filter=";
Richard Uhler03bc6592016-11-22 09:42:04 +0000241 status << CompilerFilter::NameOfFilter(odex_.GetFile()->GetCompilerFilter());
Richard Uhler46cc64f2016-11-14 14:53:55 +0000242 status << ", status=" << odex_.Status();
243 }
244
245 if (!oat_file_exists && !odex_file_exists) {
246 status << "invalid[";
247 }
248
249 status << "]";
250 return status.str();
251}
252
Richard Uhler66d874d2015-01-15 09:37:19 -0800253std::vector<std::unique_ptr<const DexFile>> OatFileAssistant::LoadDexFiles(
254 const OatFile& oat_file, const char* dex_location) {
255 std::vector<std::unique_ptr<const DexFile>> dex_files;
256
257 // Load the primary dex file.
258 std::string error_msg;
259 const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(
Richard Uhler9a37efc2016-08-05 16:32:55 -0700260 dex_location, nullptr, &error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800261 if (oat_dex_file == nullptr) {
Richard Uhler9a37efc2016-08-05 16:32:55 -0700262 LOG(WARNING) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800263 return std::vector<std::unique_ptr<const DexFile>>();
264 }
265
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700266 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800267 if (dex_file.get() == nullptr) {
268 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
269 return std::vector<std::unique_ptr<const DexFile>>();
270 }
271 dex_files.push_back(std::move(dex_file));
272
273 // Load secondary multidex files
Andreas Gampe90e34042015-04-27 20:01:52 -0700274 for (size_t i = 1; ; i++) {
275 std::string secondary_dex_location = DexFile::GetMultiDexLocation(i, dex_location);
Richard Uhler9a37efc2016-08-05 16:32:55 -0700276 oat_dex_file = oat_file.GetOatDexFile(secondary_dex_location.c_str(), nullptr);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700277 if (oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800278 // There are no more secondary dex files to load.
279 break;
280 }
281
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700282 dex_file = oat_dex_file->OpenDexFile(&error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800283 if (dex_file.get() == nullptr) {
284 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
285 return std::vector<std::unique_ptr<const DexFile>>();
286 }
287 dex_files.push_back(std::move(dex_file));
288 }
289 return dex_files;
290}
291
Richard Uhler9b994ea2015-06-24 08:44:19 -0700292bool OatFileAssistant::HasOriginalDexFiles() {
293 // Ensure GetRequiredDexChecksum has been run so that
294 // has_original_dex_files_ is initialized. We don't care about the result of
295 // GetRequiredDexChecksum.
296 GetRequiredDexChecksum();
297 return has_original_dex_files_;
298}
299
Richard Uhler95abd042015-03-24 09:51:28 -0700300OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() {
Richard Uhler743bf362016-04-19 15:39:37 -0700301 return odex_.Status();
Richard Uhler66d874d2015-01-15 09:37:19 -0800302}
303
Richard Uhler95abd042015-03-24 09:51:28 -0700304OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() {
Richard Uhler743bf362016-04-19 15:39:37 -0700305 return oat_.Status();
Richard Uhler66d874d2015-01-15 09:37:19 -0800306}
307
Richard Uhler95abd042015-03-24 09:51:28 -0700308OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800309 // Verify the dex checksum.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700310 // Note: GetOatDexFile will return null if the dex checksum doesn't match
Richard Uhler66d874d2015-01-15 09:37:19 -0800311 // what we provide, which verifies the primary dex checksum for us.
Richard Uhler9a37efc2016-08-05 16:32:55 -0700312 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800313 const uint32_t* dex_checksum_pointer = GetRequiredDexChecksum();
314 const OatFile::OatDexFile* oat_dex_file = file.GetOatDexFile(
Richard Uhler9a37efc2016-08-05 16:32:55 -0700315 dex_location_.c_str(), dex_checksum_pointer, &error_msg);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700316 if (oat_dex_file == nullptr) {
Nicolas Geoffrayf54e5df2016-12-01 10:45:08 +0000317 LOG(ERROR) << error_msg;
Richard Uhler03bc6592016-11-22 09:42:04 +0000318 return kOatDexOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800319 }
320
321 // Verify the dex checksums for any secondary multidex files
Andreas Gampe90e34042015-04-27 20:01:52 -0700322 for (size_t i = 1; ; i++) {
Richard Uhler9a37efc2016-08-05 16:32:55 -0700323 std::string secondary_dex_location = DexFile::GetMultiDexLocation(i, dex_location_.c_str());
Richard Uhler66d874d2015-01-15 09:37:19 -0800324 const OatFile::OatDexFile* secondary_oat_dex_file
Richard Uhler9a37efc2016-08-05 16:32:55 -0700325 = file.GetOatDexFile(secondary_dex_location.c_str(), nullptr);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700326 if (secondary_oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800327 // There are no more secondary dex files to check.
328 break;
329 }
330
Richard Uhler66d874d2015-01-15 09:37:19 -0800331 uint32_t expected_secondary_checksum = 0;
332 if (DexFile::GetChecksum(secondary_dex_location.c_str(),
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700333 &expected_secondary_checksum, &error_msg)) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800334 uint32_t actual_secondary_checksum
335 = secondary_oat_dex_file->GetDexFileLocationChecksum();
336 if (expected_secondary_checksum != actual_secondary_checksum) {
337 VLOG(oat) << "Dex checksum does not match for secondary dex: "
338 << secondary_dex_location
339 << ". Expected: " << expected_secondary_checksum
340 << ", Actual: " << actual_secondary_checksum;
Richard Uhler03bc6592016-11-22 09:42:04 +0000341 return kOatDexOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800342 }
343 } else {
344 // If we can't get the checksum for the secondary location, we assume
345 // the dex checksum is up to date for this and all other secondary dex
346 // files.
347 break;
348 }
349 }
350
Andreas Gampe29d38e72016-03-23 15:31:51 +0000351 CompilerFilter::Filter current_compiler_filter = file.GetCompilerFilter();
David Brazdilce4b0ba2016-01-28 15:05:49 +0000352
Richard Uhler66d874d2015-01-15 09:37:19 -0800353 // Verify the image checksum
Andreas Gampe29d38e72016-03-23 15:31:51 +0000354 if (CompilerFilter::DependsOnImageChecksum(current_compiler_filter)) {
355 const ImageInfo* image_info = GetImageInfo();
356 if (image_info == nullptr) {
357 VLOG(oat) << "No image for oat image checksum to match against.";
Andreas Gampe29d38e72016-03-23 15:31:51 +0000358
Richard Uhler76f5cb62016-04-04 13:30:16 -0700359 if (HasOriginalDexFiles()) {
Richard Uhler03bc6592016-11-22 09:42:04 +0000360 return kOatBootImageOutOfDate;
Richard Uhler76f5cb62016-04-04 13:30:16 -0700361 }
362
363 // If there is no original dex file to fall back to, grudgingly accept
364 // the oat file. This could technically lead to crashes, but there's no
365 // way we could find a better oat file to use for this dex location,
366 // and it's better than being stuck in a boot loop with no way out.
367 // The problem will hopefully resolve itself the next time the runtime
368 // starts up.
369 LOG(WARNING) << "Dex location " << dex_location_ << " does not seem to include dex file. "
370 << "Allow oat file use. This is potentially dangerous.";
371 } else if (file.GetOatHeader().GetImageFileLocationOatChecksum()
372 != GetCombinedImageChecksum()) {
Andreas Gampe29d38e72016-03-23 15:31:51 +0000373 VLOG(oat) << "Oat image checksum does not match image checksum.";
Richard Uhler03bc6592016-11-22 09:42:04 +0000374 return kOatBootImageOutOfDate;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000375 }
376 } else {
377 VLOG(oat) << "Image checksum test skipped for compiler filter " << current_compiler_filter;
Richard Uhler66d874d2015-01-15 09:37:19 -0800378 }
379
Vladimir Markof6d1e0f2016-05-23 15:32:42 +0100380 if (CompilerFilter::IsBytecodeCompilationEnabled(current_compiler_filter)) {
Andreas Gampe29d38e72016-03-23 15:31:51 +0000381 if (!file.IsPic()) {
382 const ImageInfo* image_info = GetImageInfo();
383 if (image_info == nullptr) {
384 VLOG(oat) << "No image to check oat relocation against.";
Richard Uhler03bc6592016-11-22 09:42:04 +0000385 return kOatRelocationOutOfDate;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000386 }
Richard Uhlera62d2f02016-03-18 15:05:30 -0700387
Andreas Gampe29d38e72016-03-23 15:31:51 +0000388 // Verify the oat_data_begin recorded for the image in the oat file matches
389 // the actual oat_data_begin for boot.oat in the image.
390 const OatHeader& oat_header = file.GetOatHeader();
391 uintptr_t oat_data_begin = oat_header.GetImageFileLocationOatDataBegin();
392 if (oat_data_begin != image_info->oat_data_begin) {
393 VLOG(oat) << file.GetLocation() <<
394 ": Oat file image oat_data_begin (" << oat_data_begin << ")"
395 << " does not match actual image oat_data_begin ("
396 << image_info->oat_data_begin << ")";
Richard Uhler03bc6592016-11-22 09:42:04 +0000397 return kOatRelocationOutOfDate;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000398 }
Richard Uhlera62d2f02016-03-18 15:05:30 -0700399
Andreas Gampe29d38e72016-03-23 15:31:51 +0000400 // Verify the oat_patch_delta recorded for the image in the oat file matches
401 // the actual oat_patch_delta for the image.
402 int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
403 if (oat_patch_delta != image_info->patch_delta) {
404 VLOG(oat) << file.GetLocation() <<
405 ": Oat file image patch delta (" << oat_patch_delta << ")"
406 << " does not match actual image patch delta ("
407 << image_info->patch_delta << ")";
Richard Uhler03bc6592016-11-22 09:42:04 +0000408 return kOatRelocationOutOfDate;
Andreas Gampe29d38e72016-03-23 15:31:51 +0000409 }
410 } else {
411 // Oat files compiled in PIC mode do not require relocation.
412 VLOG(oat) << "Oat relocation test skipped for PIC oat file";
413 }
414 } else {
415 VLOG(oat) << "Oat relocation test skipped for compiler filter " << current_compiler_filter;
Richard Uhler66d874d2015-01-15 09:37:19 -0800416 }
Richard Uhlere8109f72016-04-18 10:40:50 -0700417 return kOatUpToDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800418}
419
Richard Uhler1e860612016-03-30 12:17:55 -0700420OatFileAssistant::ResultOfAttemptToUpdate
421OatFileAssistant::RelocateOatFile(const std::string* input_file, std::string* error_msg) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800422 CHECK(error_msg != nullptr);
423
Richard Uhler95abd042015-03-24 09:51:28 -0700424 if (input_file == nullptr) {
Richard Uhler740eec92015-10-15 15:12:23 -0700425 *error_msg = "Patching of oat file for dex location " + dex_location_
Richard Uhler95abd042015-03-24 09:51:28 -0700426 + " not attempted because the input file name could not be determined.";
Richard Uhler1e860612016-03-30 12:17:55 -0700427 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800428 }
Richard Uhler95abd042015-03-24 09:51:28 -0700429 const std::string& input_file_name = *input_file;
Richard Uhler66d874d2015-01-15 09:37:19 -0800430
Richard Uhler743bf362016-04-19 15:39:37 -0700431 if (oat_.Filename() == nullptr) {
Richard Uhler740eec92015-10-15 15:12:23 -0700432 *error_msg = "Patching of oat file for dex location " + dex_location_
Richard Uhler66d874d2015-01-15 09:37:19 -0800433 + " not attempted because the oat file name could not be determined.";
Richard Uhler1e860612016-03-30 12:17:55 -0700434 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800435 }
Richard Uhler743bf362016-04-19 15:39:37 -0700436 const std::string& oat_file_name = *oat_.Filename();
Richard Uhler66d874d2015-01-15 09:37:19 -0800437
438 const ImageInfo* image_info = GetImageInfo();
439 Runtime* runtime = Runtime::Current();
440 if (image_info == nullptr) {
441 *error_msg = "Patching of oat file " + oat_file_name
442 + " not attempted because no image location was found.";
Richard Uhler1e860612016-03-30 12:17:55 -0700443 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800444 }
445
446 if (!runtime->IsDex2OatEnabled()) {
447 *error_msg = "Patching of oat file " + oat_file_name
448 + " not attempted because dex2oat is disabled";
Richard Uhler1e860612016-03-30 12:17:55 -0700449 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800450 }
451
452 std::vector<std::string> argv;
453 argv.push_back(runtime->GetPatchoatExecutable());
454 argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(isa_)));
Richard Uhler95abd042015-03-24 09:51:28 -0700455 argv.push_back("--input-oat-file=" + input_file_name);
Richard Uhler66d874d2015-01-15 09:37:19 -0800456 argv.push_back("--output-oat-file=" + oat_file_name);
457 argv.push_back("--patched-image-location=" + image_info->location);
458
459 std::string command_line(Join(argv, ' '));
460 if (!Exec(argv, error_msg)) {
461 // Manually delete the file. This ensures there is no garbage left over if
462 // the process unexpectedly died.
Vladimir Marko66fdcbd2016-04-05 14:19:08 +0100463 unlink(oat_file_name.c_str());
Richard Uhler1e860612016-03-30 12:17:55 -0700464 return kUpdateFailed;
Richard Uhler66d874d2015-01-15 09:37:19 -0800465 }
466
467 // Mark that the oat file has changed and we should try to reload.
Richard Uhler743bf362016-04-19 15:39:37 -0700468 oat_.Reset();
Richard Uhler1e860612016-03-30 12:17:55 -0700469 return kUpdateSucceeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800470}
471
Richard Uhler1e860612016-03-30 12:17:55 -0700472OatFileAssistant::ResultOfAttemptToUpdate
Richard Uhlerf4b34872016-04-13 11:03:46 -0700473OatFileAssistant::GenerateOatFile(std::string* error_msg) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800474 CHECK(error_msg != nullptr);
475
Richard Uhler8327cf72015-10-13 16:34:59 -0700476 Runtime* runtime = Runtime::Current();
477 if (!runtime->IsDex2OatEnabled()) {
478 *error_msg = "Generation of oat file for dex location " + dex_location_
479 + " not attempted because dex2oat is disabled.";
Richard Uhler1e860612016-03-30 12:17:55 -0700480 return kUpdateNotAttempted;
Richard Uhler8327cf72015-10-13 16:34:59 -0700481 }
482
Richard Uhler743bf362016-04-19 15:39:37 -0700483 if (oat_.Filename() == nullptr) {
Richard Uhler740eec92015-10-15 15:12:23 -0700484 *error_msg = "Generation of oat file for dex location " + dex_location_
Richard Uhler66d874d2015-01-15 09:37:19 -0800485 + " not attempted because the oat file name could not be determined.";
Richard Uhler1e860612016-03-30 12:17:55 -0700486 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800487 }
Richard Uhler743bf362016-04-19 15:39:37 -0700488 const std::string& oat_file_name = *oat_.Filename();
David Brazdil7b49e6c2016-09-01 11:06:18 +0100489 const std::string& vdex_file_name = ReplaceFileExtension(oat_file_name, "vdex");
Richard Uhler66d874d2015-01-15 09:37:19 -0800490
Richard Uhler66d874d2015-01-15 09:37:19 -0800491 // dex2oat ignores missing dex files and doesn't report an error.
492 // Check explicitly here so we can detect the error properly.
493 // TODO: Why does dex2oat behave that way?
Richard Uhler740eec92015-10-15 15:12:23 -0700494 if (!OS::FileExists(dex_location_.c_str())) {
495 *error_msg = "Dex location " + dex_location_ + " does not exists.";
Richard Uhler1e860612016-03-30 12:17:55 -0700496 return kUpdateNotAttempted;
Richard Uhler66d874d2015-01-15 09:37:19 -0800497 }
498
David Brazdil7b49e6c2016-09-01 11:06:18 +0100499 std::unique_ptr<File> vdex_file(OS::CreateEmptyFile(vdex_file_name.c_str()));
500 if (vdex_file.get() == nullptr) {
501 *error_msg = "Generation of oat file " + oat_file_name
502 + " not attempted because the vdex file " + vdex_file_name
503 + " could not be opened.";
504 return kUpdateNotAttempted;
505 }
506
507 if (fchmod(vdex_file->Fd(), 0644) != 0) {
508 *error_msg = "Generation of oat file " + oat_file_name
509 + " not attempted because the vdex file " + vdex_file_name
510 + " could not be made world readable.";
511 return kUpdateNotAttempted;
512 }
513
514 std::unique_ptr<File> oat_file(OS::CreateEmptyFile(oat_file_name.c_str()));
Richard Uhler8327cf72015-10-13 16:34:59 -0700515 if (oat_file.get() == nullptr) {
516 *error_msg = "Generation of oat file " + oat_file_name
517 + " not attempted because the oat file could not be created.";
Richard Uhler1e860612016-03-30 12:17:55 -0700518 return kUpdateNotAttempted;
Richard Uhler8327cf72015-10-13 16:34:59 -0700519 }
520
521 if (fchmod(oat_file->Fd(), 0644) != 0) {
522 *error_msg = "Generation of oat file " + oat_file_name
523 + " not attempted because the oat file could not be made world readable.";
524 oat_file->Erase();
Richard Uhler1e860612016-03-30 12:17:55 -0700525 return kUpdateNotAttempted;
Richard Uhler8327cf72015-10-13 16:34:59 -0700526 }
527
528 std::vector<std::string> args;
529 args.push_back("--dex-file=" + dex_location_);
Nicolas Geoffraya6a448a2016-11-10 10:49:40 +0000530 args.push_back("--output-vdex-fd=" + std::to_string(vdex_file->Fd()));
Richard Uhler8327cf72015-10-13 16:34:59 -0700531 args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
532 args.push_back("--oat-location=" + oat_file_name);
533
Richard Uhler66d874d2015-01-15 09:37:19 -0800534 if (!Dex2Oat(args, error_msg)) {
David Brazdil7b49e6c2016-09-01 11:06:18 +0100535 // Manually delete the oat and vdex files. This ensures there is no garbage
536 // left over if the process unexpectedly died.
537 vdex_file->Erase();
538 unlink(vdex_file_name.c_str());
Richard Uhler8327cf72015-10-13 16:34:59 -0700539 oat_file->Erase();
Vladimir Marko66fdcbd2016-04-05 14:19:08 +0100540 unlink(oat_file_name.c_str());
Richard Uhler1e860612016-03-30 12:17:55 -0700541 return kUpdateFailed;
Richard Uhler8327cf72015-10-13 16:34:59 -0700542 }
543
David Brazdil7b49e6c2016-09-01 11:06:18 +0100544 if (vdex_file->FlushCloseOrErase() != 0) {
545 *error_msg = "Unable to close vdex file " + vdex_file_name;
546 unlink(vdex_file_name.c_str());
547 return kUpdateFailed;
548 }
549
Richard Uhler8327cf72015-10-13 16:34:59 -0700550 if (oat_file->FlushCloseOrErase() != 0) {
551 *error_msg = "Unable to close oat file " + oat_file_name;
Vladimir Marko66fdcbd2016-04-05 14:19:08 +0100552 unlink(oat_file_name.c_str());
Richard Uhler1e860612016-03-30 12:17:55 -0700553 return kUpdateFailed;
Richard Uhler66d874d2015-01-15 09:37:19 -0800554 }
555
556 // Mark that the oat file has changed and we should try to reload.
Richard Uhler743bf362016-04-19 15:39:37 -0700557 oat_.Reset();
Richard Uhler1e860612016-03-30 12:17:55 -0700558 return kUpdateSucceeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800559}
560
561bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args,
562 std::string* error_msg) {
563 Runtime* runtime = Runtime::Current();
564 std::string image_location = ImageLocation();
565 if (image_location.empty()) {
566 *error_msg = "No image location found for Dex2Oat.";
567 return false;
568 }
569
570 std::vector<std::string> argv;
571 argv.push_back(runtime->GetCompilerExecutable());
572 argv.push_back("--runtime-arg");
573 argv.push_back("-classpath");
574 argv.push_back("--runtime-arg");
Jeff Haof0192c82016-03-28 20:39:50 -0700575 std::string class_path = runtime->GetClassPathString();
576 if (class_path == "") {
577 class_path = OatFile::kSpecialSharedLibrary;
578 }
579 argv.push_back(class_path);
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +0100580 if (runtime->IsDebuggable()) {
Sebastien Hertz0de11332015-05-13 12:14:05 +0200581 argv.push_back("--debuggable");
582 }
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700583 runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
Richard Uhler66d874d2015-01-15 09:37:19 -0800584
585 if (!runtime->IsVerificationEnabled()) {
586 argv.push_back("--compiler-filter=verify-none");
587 }
588
589 if (runtime->MustRelocateIfPossible()) {
590 argv.push_back("--runtime-arg");
591 argv.push_back("-Xrelocate");
592 } else {
593 argv.push_back("--runtime-arg");
594 argv.push_back("-Xnorelocate");
595 }
596
597 if (!kIsTargetBuild) {
598 argv.push_back("--host");
599 }
600
601 argv.push_back("--boot-image=" + image_location);
602
603 std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
604 argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
605
606 argv.insert(argv.end(), args.begin(), args.end());
607
608 std::string command_line(Join(argv, ' '));
609 return Exec(argv, error_msg);
610}
611
Richard Uhlerb81881d2016-04-19 13:08:04 -0700612bool OatFileAssistant::DexLocationToOdexFilename(const std::string& location,
613 InstructionSet isa,
614 std::string* odex_filename,
615 std::string* error_msg) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800616 CHECK(odex_filename != nullptr);
617 CHECK(error_msg != nullptr);
618
619 // The odex file name is formed by replacing the dex_location extension with
Richard Uhler63434112015-03-16 14:32:16 -0700620 // .odex and inserting an oat/<isa> directory. For example:
Richard Uhler66d874d2015-01-15 09:37:19 -0800621 // location = /foo/bar/baz.jar
Richard Uhler63434112015-03-16 14:32:16 -0700622 // odex_location = /foo/bar/oat/<isa>/baz.odex
Richard Uhler66d874d2015-01-15 09:37:19 -0800623
Richard Uhler63434112015-03-16 14:32:16 -0700624 // Find the directory portion of the dex location and add the oat/<isa>
625 // directory.
Richard Uhler66d874d2015-01-15 09:37:19 -0800626 size_t pos = location.rfind('/');
627 if (pos == std::string::npos) {
628 *error_msg = "Dex location " + location + " has no directory.";
629 return false;
630 }
631 std::string dir = location.substr(0, pos+1);
Richard Uhler63434112015-03-16 14:32:16 -0700632 dir += "oat/" + std::string(GetInstructionSetString(isa));
Richard Uhler66d874d2015-01-15 09:37:19 -0800633
634 // Find the file portion of the dex location.
635 std::string file;
636 if (pos == std::string::npos) {
637 file = location;
638 } else {
639 file = location.substr(pos+1);
640 }
641
642 // Get the base part of the file without the extension.
643 pos = file.rfind('.');
644 if (pos == std::string::npos) {
645 *error_msg = "Dex location " + location + " has no extension.";
646 return false;
647 }
648 std::string base = file.substr(0, pos);
649
650 *odex_filename = dir + "/" + base + ".odex";
651 return true;
652}
653
Richard Uhlerb81881d2016-04-19 13:08:04 -0700654bool OatFileAssistant::DexLocationToOatFilename(const std::string& location,
655 InstructionSet isa,
656 std::string* oat_filename,
657 std::string* error_msg) {
658 CHECK(oat_filename != nullptr);
659 CHECK(error_msg != nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800660
Richard Uhler55b58b62016-08-12 09:05:13 -0700661 std::string cache_dir = GetDalvikCache(GetInstructionSetString(isa));
662 if (cache_dir.empty()) {
663 *error_msg = "Dalvik cache directory does not exist";
664 return false;
665 }
Richard Uhlerb81881d2016-04-19 13:08:04 -0700666
667 // TODO: The oat file assistant should be the definitive place for
668 // determining the oat file name from the dex location, not
669 // GetDalvikCacheFilename.
Richard Uhlerb81881d2016-04-19 13:08:04 -0700670 return GetDalvikCacheFilename(location.c_str(), cache_dir.c_str(), oat_filename, error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800671}
672
Richard Uhler66d874d2015-01-15 09:37:19 -0800673std::string OatFileAssistant::ImageLocation() {
674 Runtime* runtime = Runtime::Current();
Andreas Gampe8994a042015-12-30 19:03:17 +0000675 const std::vector<gc::space::ImageSpace*>& image_spaces =
676 runtime->GetHeap()->GetBootImageSpaces();
677 if (image_spaces.empty()) {
678 return "";
679 }
680 return image_spaces[0]->GetImageLocation();
Richard Uhler66d874d2015-01-15 09:37:19 -0800681}
682
683const uint32_t* OatFileAssistant::GetRequiredDexChecksum() {
Richard Uhler9b994ea2015-06-24 08:44:19 -0700684 if (!required_dex_checksum_attempted_) {
685 required_dex_checksum_attempted_ = true;
686 required_dex_checksum_found_ = false;
Richard Uhler66d874d2015-01-15 09:37:19 -0800687 std::string error_msg;
Richard Uhler740eec92015-10-15 15:12:23 -0700688 if (DexFile::GetChecksum(dex_location_.c_str(), &cached_required_dex_checksum_, &error_msg)) {
Richard Uhler9b994ea2015-06-24 08:44:19 -0700689 required_dex_checksum_found_ = true;
690 has_original_dex_files_ = true;
Richard Uhler66d874d2015-01-15 09:37:19 -0800691 } else {
692 // This can happen if the original dex file has been stripped from the
693 // apk.
694 VLOG(oat) << "OatFileAssistant: " << error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700695 has_original_dex_files_ = false;
Richard Uhler66d874d2015-01-15 09:37:19 -0800696
697 // Get the checksum from the odex if we can.
Richard Uhler743bf362016-04-19 15:39:37 -0700698 const OatFile* odex_file = odex_.GetFile();
Richard Uhler66d874d2015-01-15 09:37:19 -0800699 if (odex_file != nullptr) {
Richard Uhler9a37efc2016-08-05 16:32:55 -0700700 const OatFile::OatDexFile* odex_dex_file
701 = odex_file->GetOatDexFile(dex_location_.c_str(), nullptr);
Richard Uhler66d874d2015-01-15 09:37:19 -0800702 if (odex_dex_file != nullptr) {
Richard Uhler9b994ea2015-06-24 08:44:19 -0700703 cached_required_dex_checksum_ = odex_dex_file->GetDexFileLocationChecksum();
704 required_dex_checksum_found_ = true;
Richard Uhler66d874d2015-01-15 09:37:19 -0800705 }
706 }
707 }
708 }
Richard Uhler9b994ea2015-06-24 08:44:19 -0700709 return required_dex_checksum_found_ ? &cached_required_dex_checksum_ : nullptr;
Richard Uhler66d874d2015-01-15 09:37:19 -0800710}
711
Richard Uhler66d874d2015-01-15 09:37:19 -0800712const OatFileAssistant::ImageInfo* OatFileAssistant::GetImageInfo() {
713 if (!image_info_load_attempted_) {
714 image_info_load_attempted_ = true;
715
716 Runtime* runtime = Runtime::Current();
Jeff Haodcdc85b2015-12-04 14:06:18 -0800717 std::vector<gc::space::ImageSpace*> image_spaces = runtime->GetHeap()->GetBootImageSpaces();
718 if (!image_spaces.empty()) {
Jeff Haodcdc85b2015-12-04 14:06:18 -0800719 cached_image_info_.location = image_spaces[0]->GetImageLocation();
Richard Uhler66d874d2015-01-15 09:37:19 -0800720
721 if (isa_ == kRuntimeISA) {
Jeff Haodcdc85b2015-12-04 14:06:18 -0800722 const ImageHeader& image_header = image_spaces[0]->GetImageHeader();
Richard Uhler66d874d2015-01-15 09:37:19 -0800723 cached_image_info_.oat_checksum = image_header.GetOatChecksum();
Mathieu Chartier073b16c2015-11-10 14:13:23 -0800724 cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(
725 image_header.GetOatDataBegin());
Richard Uhler66d874d2015-01-15 09:37:19 -0800726 cached_image_info_.patch_delta = image_header.GetPatchDelta();
727 } else {
Andreas Gampea463b6a2016-08-12 21:53:32 -0700728 std::string error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800729 std::unique_ptr<ImageHeader> image_header(
Andreas Gampea463b6a2016-08-12 21:53:32 -0700730 gc::space::ImageSpace::ReadImageHeader(cached_image_info_.location.c_str(),
731 isa_,
732 &error_msg));
733 CHECK(image_header != nullptr) << error_msg;
Richard Uhler66d874d2015-01-15 09:37:19 -0800734 cached_image_info_.oat_checksum = image_header->GetOatChecksum();
Mathieu Chartier073b16c2015-11-10 14:13:23 -0800735 cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(
736 image_header->GetOatDataBegin());
Richard Uhler66d874d2015-01-15 09:37:19 -0800737 cached_image_info_.patch_delta = image_header->GetPatchDelta();
738 }
739 }
Jeff Haodcdc85b2015-12-04 14:06:18 -0800740 image_info_load_succeeded_ = (!image_spaces.empty());
Jeff Haob11ffb72016-04-07 15:40:54 -0700741
Jeff Haofd336c32016-04-07 19:46:31 -0700742 combined_image_checksum_ = CalculateCombinedImageChecksum(isa_);
Richard Uhler66d874d2015-01-15 09:37:19 -0800743 }
744 return image_info_load_succeeded_ ? &cached_image_info_ : nullptr;
745}
746
Jeff Haob11ffb72016-04-07 15:40:54 -0700747// TODO: Use something better than xor.
Jeff Haofd336c32016-04-07 19:46:31 -0700748uint32_t OatFileAssistant::CalculateCombinedImageChecksum(InstructionSet isa) {
Jeff Haob11ffb72016-04-07 15:40:54 -0700749 uint32_t checksum = 0;
750 std::vector<gc::space::ImageSpace*> image_spaces =
751 Runtime::Current()->GetHeap()->GetBootImageSpaces();
Jeff Haofd336c32016-04-07 19:46:31 -0700752 if (isa == kRuntimeISA) {
753 for (gc::space::ImageSpace* image_space : image_spaces) {
754 checksum ^= image_space->GetImageHeader().GetOatChecksum();
755 }
756 } else {
757 for (gc::space::ImageSpace* image_space : image_spaces) {
758 std::string location = image_space->GetImageLocation();
Andreas Gampea463b6a2016-08-12 21:53:32 -0700759 std::string error_msg;
Jeff Haofd336c32016-04-07 19:46:31 -0700760 std::unique_ptr<ImageHeader> image_header(
Andreas Gampea463b6a2016-08-12 21:53:32 -0700761 gc::space::ImageSpace::ReadImageHeader(location.c_str(), isa, &error_msg));
762 CHECK(image_header != nullptr) << error_msg;
Jeff Haofd336c32016-04-07 19:46:31 -0700763 checksum ^= image_header->GetOatChecksum();
764 }
Jeff Haob11ffb72016-04-07 15:40:54 -0700765 }
766 return checksum;
767}
768
769uint32_t OatFileAssistant::GetCombinedImageChecksum() {
770 if (!image_info_load_attempted_) {
771 GetImageInfo();
772 }
773 return combined_image_checksum_;
774}
775
Richard Uhler88bc6732016-11-14 14:38:03 +0000776OatFileAssistant::OatFileInfo& OatFileAssistant::GetBestInfo() {
Richard Uhler03bc6592016-11-22 09:42:04 +0000777 bool use_oat = oat_.IsUseable() || odex_.Status() == kOatCannotOpen;
778 return use_oat ? oat_ : odex_;
Richard Uhler88bc6732016-11-14 14:38:03 +0000779}
780
Andreas Gampea463b6a2016-08-12 21:53:32 -0700781std::unique_ptr<gc::space::ImageSpace> OatFileAssistant::OpenImageSpace(const OatFile* oat_file) {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800782 DCHECK(oat_file != nullptr);
David Brazdil7b49e6c2016-09-01 11:06:18 +0100783 std::string art_file = ReplaceFileExtension(oat_file->GetLocation(), "art");
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800784 if (art_file.empty()) {
785 return nullptr;
786 }
787 std::string error_msg;
788 ScopedObjectAccess soa(Thread::Current());
Andreas Gampea463b6a2016-08-12 21:53:32 -0700789 std::unique_ptr<gc::space::ImageSpace> ret =
790 gc::space::ImageSpace::CreateFromAppImage(art_file.c_str(), oat_file, &error_msg);
Mathieu Chartiere778fc72016-01-25 20:11:28 -0800791 if (ret == nullptr && (VLOG_IS_ON(image) || OS::FileExists(art_file.c_str()))) {
Mathieu Chartierfbc31082016-01-24 11:59:56 -0800792 LOG(INFO) << "Failed to open app image " << art_file.c_str() << " " << error_msg;
793 }
794 return ret;
795}
796
Richard Uhler88bc6732016-11-14 14:38:03 +0000797OatFileAssistant::OatFileInfo::OatFileInfo(OatFileAssistant* oat_file_assistant,
798 bool is_oat_location)
799 : oat_file_assistant_(oat_file_assistant), is_oat_location_(is_oat_location)
Richard Uhler743bf362016-04-19 15:39:37 -0700800{}
801
Richard Uhler88bc6732016-11-14 14:38:03 +0000802bool OatFileAssistant::OatFileInfo::IsOatLocation() {
803 return is_oat_location_;
804}
805
Richard Uhler743bf362016-04-19 15:39:37 -0700806const std::string* OatFileAssistant::OatFileInfo::Filename() {
807 return filename_provided_ ? &filename_ : nullptr;
808}
809
Richard Uhler03bc6592016-11-22 09:42:04 +0000810bool OatFileAssistant::OatFileInfo::IsUseable() {
811 switch (Status()) {
812 case kOatCannotOpen:
813 case kOatDexOutOfDate:
814 case kOatBootImageOutOfDate: return false;
815
816 case kOatRelocationOutOfDate:
817 case kOatUpToDate: return true;
818 }
819 UNREACHABLE();
Richard Uhler743bf362016-04-19 15:39:37 -0700820}
821
822OatFileAssistant::OatStatus OatFileAssistant::OatFileInfo::Status() {
823 if (!status_attempted_) {
824 status_attempted_ = true;
825 const OatFile* file = GetFile();
826 if (file == nullptr) {
Richard Uhler03bc6592016-11-22 09:42:04 +0000827 status_ = kOatCannotOpen;
Richard Uhler743bf362016-04-19 15:39:37 -0700828 } else {
829 status_ = oat_file_assistant_->GivenOatFileStatus(*file);
Richard Uhler9a37efc2016-08-05 16:32:55 -0700830 VLOG(oat) << file->GetLocation() << " is " << status_
831 << " with filter " << file->GetCompilerFilter();
Richard Uhler743bf362016-04-19 15:39:37 -0700832 }
833 }
834 return status_;
835}
836
Richard Uhler70a84262016-11-08 16:51:51 +0000837OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded(
838 CompilerFilter::Filter target, bool profile_changed) {
839 bool compilation_desired = CompilerFilter::IsBytecodeCompilationEnabled(target);
Richard Uhler7225a8d2016-11-22 10:12:03 +0000840 bool filter_okay = CompilerFilterIsOkay(target, profile_changed);
Richard Uhler70a84262016-11-08 16:51:51 +0000841
Richard Uhler7225a8d2016-11-22 10:12:03 +0000842 if (filter_okay && Status() == kOatUpToDate) {
843 // The oat file is in good shape as is.
844 return kNoDexOptNeeded;
Richard Uhler70a84262016-11-08 16:51:51 +0000845 }
846
Richard Uhler7225a8d2016-11-22 10:12:03 +0000847 if (filter_okay && !compilation_desired && Status() == kOatRelocationOutOfDate) {
848 // If no compilation is desired, then it doesn't matter if the oat
849 // file needs relocation. It's in good shape as is.
850 return kNoDexOptNeeded;
851 }
852
853 if (filter_okay && Status() == kOatRelocationOutOfDate && HasPatchInfo()) {
854 return kPatchoatForRelocation;
855 }
856
857 if (oat_file_assistant_->HasOriginalDexFiles()) {
858 // Run dex2oat for relocation if we didn't have the patch info necessary
859 // to use patchoat.
860 if (filter_okay && Status() == kOatRelocationOutOfDate) {
861 return kDex2OatForRelocation;
862 }
863
864 if (IsUseable()) {
865 return kDex2OatForFilter;
866 }
867
868 if (Status() == kOatBootImageOutOfDate) {
869 return kDex2OatForBootImage;
870 }
871
872 return kDex2OatFromScratch;
873 }
874
875 // Otherwise there is nothing we can do, even if we want to.
876 return kNoDexOptNeeded;
Richard Uhler70a84262016-11-08 16:51:51 +0000877}
878
Richard Uhler743bf362016-04-19 15:39:37 -0700879const OatFile* OatFileAssistant::OatFileInfo::GetFile() {
880 CHECK(!file_released_) << "GetFile called after oat file released.";
881 if (!load_attempted_) {
882 load_attempted_ = true;
883 if (filename_provided_) {
884 std::string error_msg;
885 file_.reset(OatFile::Open(filename_.c_str(),
886 filename_.c_str(),
887 nullptr,
888 nullptr,
889 oat_file_assistant_->load_executable_,
890 /*low_4gb*/false,
891 oat_file_assistant_->dex_location_.c_str(),
892 &error_msg));
893 if (file_.get() == nullptr) {
894 VLOG(oat) << "OatFileAssistant test for existing oat file "
895 << filename_ << ": " << error_msg;
896 }
897 }
898 }
899 return file_.get();
900}
901
902bool OatFileAssistant::OatFileInfo::CompilerFilterIsOkay(
903 CompilerFilter::Filter target, bool profile_changed) {
904 const OatFile* file = GetFile();
905 if (file == nullptr) {
906 return false;
907 }
908
909 CompilerFilter::Filter current = file->GetCompilerFilter();
910 if (profile_changed && CompilerFilter::DependsOnProfile(current)) {
911 VLOG(oat) << "Compiler filter not okay because Profile changed";
912 return false;
913 }
914 return CompilerFilter::IsAsGoodAs(current, target);
915}
916
917bool OatFileAssistant::OatFileInfo::IsExecutable() {
918 const OatFile* file = GetFile();
919 return (file != nullptr && file->IsExecutable());
920}
921
922bool OatFileAssistant::OatFileInfo::HasPatchInfo() {
923 const OatFile* file = GetFile();
924 return (file != nullptr && file->HasPatchInfo());
925}
926
927void OatFileAssistant::OatFileInfo::Reset() {
928 load_attempted_ = false;
929 file_.reset();
930 status_attempted_ = false;
931}
932
933void OatFileAssistant::OatFileInfo::Reset(const std::string& filename) {
934 filename_provided_ = true;
935 filename_ = filename;
936 Reset();
937}
938
939std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFile() {
940 file_released_ = true;
941 return std::move(file_);
942}
943
Richard Uhler70a84262016-11-08 16:51:51 +0000944std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFileForUse() {
Richard Uhler3e580bc2016-11-08 16:23:07 +0000945 if (Status() == kOatUpToDate) {
Richard Uhler70a84262016-11-08 16:51:51 +0000946 return ReleaseFile();
947 }
948
949 VLOG(oat) << "Oat File Assistant: No relocated oat file found,"
950 << " attempting to fall back to interpreting oat file instead.";
951
Richard Uhler03bc6592016-11-22 09:42:04 +0000952 if (Status() == kOatRelocationOutOfDate && !IsExecutable()) {
Richard Uhler70a84262016-11-08 16:51:51 +0000953 return ReleaseFile();
954 }
955
Richard Uhler03bc6592016-11-22 09:42:04 +0000956 if (Status() == kOatRelocationOutOfDate) {
Richard Uhler70a84262016-11-08 16:51:51 +0000957 // We are loading an oat file for runtime use that needs relocation.
958 // Reload the file non-executable to ensure that we interpret out of the
959 // dex code in the oat file rather than trying to execute the unrelocated
960 // compiled code.
961 oat_file_assistant_->load_executable_ = false;
962 Reset();
Richard Uhler03bc6592016-11-22 09:42:04 +0000963 if (IsUseable()) {
Richard Uhler70a84262016-11-08 16:51:51 +0000964 CHECK(!IsExecutable());
965 return ReleaseFile();
966 }
967 }
968 return std::unique_ptr<OatFile>();
969}
Richard Uhler66d874d2015-01-15 09:37:19 -0800970} // namespace art
971