blob: 2f672632854754ced845550b23be902a3e7a8c29 [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
19#include <fcntl.h>
20#ifdef __linux__
21#include <sys/sendfile.h>
22#else
23#include <sys/socket.h>
24#endif
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <unistd.h>
28
29#include <set>
30
31#include "base/logging.h"
32#include "base/stringprintf.h"
33#include "class_linker.h"
34#include "gc/heap.h"
35#include "gc/space/image_space.h"
36#include "image.h"
37#include "oat.h"
38#include "os.h"
39#include "profiler.h"
40#include "runtime.h"
41#include "ScopedFd.h"
42#include "utils.h"
43
44namespace art {
45
46OatFileAssistant::OatFileAssistant(const char* dex_location,
47 const InstructionSet isa,
48 bool load_executable)
49 : OatFileAssistant(dex_location, nullptr, isa, load_executable, nullptr) { }
50
51OatFileAssistant::OatFileAssistant(const char* dex_location,
52 const char* oat_location,
53 const InstructionSet isa,
54 bool load_executable)
55 : OatFileAssistant(dex_location, oat_location, isa, load_executable, nullptr) { }
56
57OatFileAssistant::OatFileAssistant(const char* dex_location,
58 const InstructionSet isa,
59 bool load_executable,
60 const char* package_name)
61 : OatFileAssistant(dex_location, nullptr, isa, load_executable, package_name) { }
62
63OatFileAssistant::OatFileAssistant(const char* dex_location,
64 const char* oat_location,
65 const InstructionSet isa,
66 bool load_executable,
67 const char* package_name)
68 : dex_location_(dex_location), isa_(isa),
69 package_name_(package_name), load_executable_(load_executable) {
70 if (load_executable_ && isa != kRuntimeISA) {
71 LOG(WARNING) << "OatFileAssistant: Load executable specified, "
72 << "but isa is not kRuntimeISA. Will not attempt to load executable.";
73 load_executable_ = false;
74 }
75
76 // If the user gave a target oat location, save that as the cached oat
77 // location now so we won't try to construct the default location later.
78 if (oat_location != nullptr) {
79 cached_oat_file_name_ = std::string(oat_location);
80 cached_oat_file_name_attempted_ = true;
81 cached_oat_file_name_found_ = true;
82 }
83
84 // If there is no package name given, we will not be able to find any
85 // profiles associated with this dex location. Preemptively mark that to
86 // be the case, rather than trying to find and load the profiles later.
87 // Similarly, if profiling is disabled.
88 if (package_name == nullptr
89 || !Runtime::Current()->GetProfilerOptions().IsEnabled()) {
90 profile_load_attempted_ = true;
91 profile_load_succeeded_ = false;
92 old_profile_load_attempted_ = true;
93 old_profile_load_succeeded_ = false;
94 }
95}
96
97OatFileAssistant::~OatFileAssistant() {
98 // Clean up the lock file.
99 if (lock_file_.get() != nullptr) {
100 lock_file_->Erase();
101 TEMP_FAILURE_RETRY(unlink(lock_file_->GetPath().c_str()));
102 }
103}
104
105bool OatFileAssistant::IsInBootClassPath() {
106 // Note: We check the current boot class path, regardless of the ISA
107 // specified by the user. This is okay, because the boot class path should
108 // be the same for all ISAs.
109 // TODO: Can we verify the boot class path is the same for all ISAs?
110 Runtime* runtime = Runtime::Current();
111 ClassLinker* class_linker = runtime->GetClassLinker();
112 const auto& boot_class_path = class_linker->GetBootClassPath();
113 for (size_t i = 0; i < boot_class_path.size(); i++) {
114 if (boot_class_path[i]->GetLocation() == std::string(dex_location_)) {
115 VLOG(oat) << "Dex location " << dex_location_ << " is in boot class path";
116 return true;
117 }
118 }
119 return false;
120}
121
122bool OatFileAssistant::Lock(std::string* error_msg) {
123 CHECK(error_msg != nullptr);
124 CHECK(lock_file_.get() == nullptr) << "OatFileAssistant::Lock already acquired";
125
126 if (OatFileName() == nullptr) {
127 *error_msg = "Failed to determine lock file";
128 return false;
129 }
130 std::string lock_file_name = *OatFileName() + ".flock";
131
132 lock_file_.reset(OS::CreateEmptyFile(lock_file_name.c_str()));
133 if (lock_file_.get() == nullptr) {
134 *error_msg = "Failed to create lock file " + lock_file_name;
135 return false;
136 }
137
138 if (!flock_.Init(lock_file_.get(), error_msg)) {
139 TEMP_FAILURE_RETRY(unlink(lock_file_name.c_str()));
140 return false;
141 }
142 return true;
143}
144
Richard Uhler95abd042015-03-24 09:51:28 -0700145OatFileAssistant::DexOptNeeded OatFileAssistant::GetDexOptNeeded() {
Richard Uhler66d874d2015-01-15 09:37:19 -0800146 // TODO: If the profiling code is ever restored, it's worth considering
147 // whether we should check to see if the profile is out of date here.
148
Richard Uhler95abd042015-03-24 09:51:28 -0700149 if (OatFileIsUpToDate() || OdexFileIsUpToDate()) {
150 return kNoDexOptNeeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800151 }
Richard Uhler95abd042015-03-24 09:51:28 -0700152
153 if (OdexFileNeedsRelocation()) {
154 return kPatchOatNeeded;
155 }
156
157 if (OatFileNeedsRelocation()) {
158 return kSelfPatchOatNeeded;
159 }
160
161 return kDex2OatNeeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800162}
163
164bool OatFileAssistant::MakeUpToDate(std::string* error_msg) {
Richard Uhler95abd042015-03-24 09:51:28 -0700165 switch (GetDexOptNeeded()) {
166 case kNoDexOptNeeded: return true;
167 case kDex2OatNeeded: return GenerateOatFile(error_msg);
168 case kPatchOatNeeded: return RelocateOatFile(OdexFileName(), error_msg);
169 case kSelfPatchOatNeeded: return RelocateOatFile(OatFileName(), error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800170 }
171 UNREACHABLE();
172}
173
174std::unique_ptr<OatFile> OatFileAssistant::GetBestOatFile() {
175 if (OatFileIsUpToDate()) {
176 oat_file_released_ = true;
177 return std::move(cached_oat_file_);
178 }
179
180 if (OdexFileIsUpToDate()) {
181 oat_file_released_ = true;
182 return std::move(cached_odex_file_);
183 }
184
185 if (load_executable_) {
186 VLOG(oat) << "Oat File Assistant: No relocated oat file found,"
187 << " attempting to fall back to interpreting oat file instead.";
188
189 if (!OatFileIsOutOfDate()) {
190 load_executable_ = false;
191 ClearOatFileCache();
192 if (!OatFileIsOutOfDate()) {
193 oat_file_released_ = true;
194 return std::move(cached_oat_file_);
195 }
196 }
197
198 if (!OdexFileIsOutOfDate()) {
199 load_executable_ = false;
200 ClearOdexFileCache();
201 if (!OdexFileIsOutOfDate()) {
202 oat_file_released_ = true;
203 return std::move(cached_odex_file_);
204 }
205 }
206 }
207
208 return std::unique_ptr<OatFile>();
209}
210
211std::vector<std::unique_ptr<const DexFile>> OatFileAssistant::LoadDexFiles(
212 const OatFile& oat_file, const char* dex_location) {
213 std::vector<std::unique_ptr<const DexFile>> dex_files;
214
215 // Load the primary dex file.
216 std::string error_msg;
217 const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(
218 dex_location, nullptr, false);
219 if (oat_dex_file == nullptr) {
220 LOG(WARNING) << "Attempt to load out-of-date oat file "
221 << oat_file.GetLocation() << " for dex location " << dex_location;
222 return std::vector<std::unique_ptr<const DexFile>>();
223 }
224
225 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
226 if (dex_file.get() == nullptr) {
227 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
228 return std::vector<std::unique_ptr<const DexFile>>();
229 }
230 dex_files.push_back(std::move(dex_file));
231
232 // Load secondary multidex files
Andreas Gampe90e34042015-04-27 20:01:52 -0700233 for (size_t i = 1; ; i++) {
234 std::string secondary_dex_location = DexFile::GetMultiDexLocation(i, dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -0800235 oat_dex_file = oat_file.GetOatDexFile(secondary_dex_location.c_str(), nullptr, false);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700236 if (oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800237 // There are no more secondary dex files to load.
238 break;
239 }
240
241 dex_file = oat_dex_file->OpenDexFile(&error_msg);
242 if (dex_file.get() == nullptr) {
243 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
244 return std::vector<std::unique_ptr<const DexFile>>();
245 }
246 dex_files.push_back(std::move(dex_file));
247 }
248 return dex_files;
249}
250
251const std::string* OatFileAssistant::OdexFileName() {
252 if (!cached_odex_file_name_attempted_) {
253 CHECK(dex_location_ != nullptr) << "OatFileAssistant: null dex location";
254 cached_odex_file_name_attempted_ = true;
255
256 std::string error_msg;
257 cached_odex_file_name_found_ = DexFilenameToOdexFilename(
258 dex_location_, isa_, &cached_odex_file_name_, &error_msg);
259 if (!cached_odex_file_name_found_) {
260 // If we can't figure out the odex file, we treat it as if the odex
261 // file was inaccessible.
262 LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
263 }
264 }
265 return cached_odex_file_name_found_ ? &cached_odex_file_name_ : nullptr;
266}
267
268bool OatFileAssistant::OdexFileExists() {
269 return GetOdexFile() != nullptr;
270}
271
Richard Uhler95abd042015-03-24 09:51:28 -0700272OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() {
Richard Uhler66d874d2015-01-15 09:37:19 -0800273 if (OdexFileIsOutOfDate()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700274 return kOatOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800275 }
276 if (OdexFileIsUpToDate()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700277 return kOatUpToDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800278 }
Richard Uhler95abd042015-03-24 09:51:28 -0700279 return kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800280}
281
282bool OatFileAssistant::OdexFileIsOutOfDate() {
283 if (!odex_file_is_out_of_date_attempted_) {
284 odex_file_is_out_of_date_attempted_ = true;
285 const OatFile* odex_file = GetOdexFile();
286 if (odex_file == nullptr) {
287 cached_odex_file_is_out_of_date_ = true;
288 } else {
289 cached_odex_file_is_out_of_date_ = GivenOatFileIsOutOfDate(*odex_file);
290 }
291 }
292 return cached_odex_file_is_out_of_date_;
293}
294
295bool OatFileAssistant::OdexFileNeedsRelocation() {
Richard Uhler95abd042015-03-24 09:51:28 -0700296 return OdexFileStatus() == kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800297}
298
299bool OatFileAssistant::OdexFileIsUpToDate() {
300 if (!odex_file_is_up_to_date_attempted_) {
301 odex_file_is_up_to_date_attempted_ = true;
302 const OatFile* odex_file = GetOdexFile();
303 if (odex_file == nullptr) {
304 cached_odex_file_is_up_to_date_ = false;
305 } else {
306 cached_odex_file_is_up_to_date_ = GivenOatFileIsUpToDate(*odex_file);
307 }
308 }
309 return cached_odex_file_is_up_to_date_;
310}
311
312const std::string* OatFileAssistant::OatFileName() {
313 if (!cached_oat_file_name_attempted_) {
314 cached_oat_file_name_attempted_ = true;
315
316 // Compute the oat file name from the dex location.
317 CHECK(dex_location_ != nullptr) << "OatFileAssistant: null dex location";
318
319 // TODO: The oat file assistant should be the definitive place for
320 // determining the oat file name from the dex location, not
321 // GetDalvikCacheFilename.
322 std::string cache_dir = StringPrintf("%s%s",
323 DalvikCacheDirectory().c_str(), GetInstructionSetString(isa_));
324 std::string error_msg;
325 cached_oat_file_name_found_ = GetDalvikCacheFilename(dex_location_,
326 cache_dir.c_str(), &cached_oat_file_name_, &error_msg);
327 if (!cached_oat_file_name_found_) {
328 // If we can't determine the oat file name, we treat the oat file as
329 // inaccessible.
330 LOG(WARNING) << "Failed to determine oat file name for dex location "
331 << dex_location_ << ": " << error_msg;
332 }
333 }
334 return cached_oat_file_name_found_ ? &cached_oat_file_name_ : nullptr;
335}
336
337bool OatFileAssistant::OatFileExists() {
338 return GetOatFile() != nullptr;
339}
340
Richard Uhler95abd042015-03-24 09:51:28 -0700341OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() {
Richard Uhler66d874d2015-01-15 09:37:19 -0800342 if (OatFileIsOutOfDate()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700343 return kOatOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800344 }
345 if (OatFileIsUpToDate()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700346 return kOatUpToDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800347 }
Richard Uhler95abd042015-03-24 09:51:28 -0700348 return kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800349}
350
351bool OatFileAssistant::OatFileIsOutOfDate() {
352 if (!oat_file_is_out_of_date_attempted_) {
353 oat_file_is_out_of_date_attempted_ = true;
354 const OatFile* oat_file = GetOatFile();
355 if (oat_file == nullptr) {
356 cached_oat_file_is_out_of_date_ = true;
357 } else {
358 cached_oat_file_is_out_of_date_ = GivenOatFileIsOutOfDate(*oat_file);
359 }
360 }
361 return cached_oat_file_is_out_of_date_;
362}
363
364bool OatFileAssistant::OatFileNeedsRelocation() {
Richard Uhler95abd042015-03-24 09:51:28 -0700365 return OatFileStatus() == kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800366}
367
368bool OatFileAssistant::OatFileIsUpToDate() {
369 if (!oat_file_is_up_to_date_attempted_) {
370 oat_file_is_up_to_date_attempted_ = true;
371 const OatFile* oat_file = GetOatFile();
372 if (oat_file == nullptr) {
373 cached_oat_file_is_up_to_date_ = false;
374 } else {
375 cached_oat_file_is_up_to_date_ = GivenOatFileIsUpToDate(*oat_file);
376 }
377 }
378 return cached_oat_file_is_up_to_date_;
379}
380
Richard Uhler95abd042015-03-24 09:51:28 -0700381OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800382 // TODO: This could cause GivenOatFileIsOutOfDate to be called twice, which
383 // is more work than we need to do. If performance becomes a concern, and
384 // this method is actually called, this should be fixed.
385 if (GivenOatFileIsOutOfDate(file)) {
Richard Uhler95abd042015-03-24 09:51:28 -0700386 return kOatOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800387 }
388 if (GivenOatFileIsUpToDate(file)) {
Richard Uhler95abd042015-03-24 09:51:28 -0700389 return kOatUpToDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800390 }
Richard Uhler95abd042015-03-24 09:51:28 -0700391 return kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800392}
393
394bool OatFileAssistant::GivenOatFileIsOutOfDate(const OatFile& file) {
395 // Verify the dex checksum.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700396 // Note: GetOatDexFile will return null if the dex checksum doesn't match
Richard Uhler66d874d2015-01-15 09:37:19 -0800397 // what we provide, which verifies the primary dex checksum for us.
398 const uint32_t* dex_checksum_pointer = GetRequiredDexChecksum();
399 const OatFile::OatDexFile* oat_dex_file = file.GetOatDexFile(
400 dex_location_, dex_checksum_pointer, false);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700401 if (oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800402 return true;
403 }
404
405 // Verify the dex checksums for any secondary multidex files
Andreas Gampe90e34042015-04-27 20:01:52 -0700406 for (size_t i = 1; ; i++) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800407 std::string secondary_dex_location
Andreas Gampe90e34042015-04-27 20:01:52 -0700408 = DexFile::GetMultiDexLocation(i, dex_location_);
Richard Uhler66d874d2015-01-15 09:37:19 -0800409 const OatFile::OatDexFile* secondary_oat_dex_file
410 = file.GetOatDexFile(secondary_dex_location.c_str(), nullptr, false);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700411 if (secondary_oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800412 // There are no more secondary dex files to check.
413 break;
414 }
415
416 std::string error_msg;
417 uint32_t expected_secondary_checksum = 0;
418 if (DexFile::GetChecksum(secondary_dex_location.c_str(),
419 &expected_secondary_checksum, &error_msg)) {
420 uint32_t actual_secondary_checksum
421 = secondary_oat_dex_file->GetDexFileLocationChecksum();
422 if (expected_secondary_checksum != actual_secondary_checksum) {
423 VLOG(oat) << "Dex checksum does not match for secondary dex: "
424 << secondary_dex_location
425 << ". Expected: " << expected_secondary_checksum
426 << ", Actual: " << actual_secondary_checksum;
427 return false;
428 }
429 } else {
430 // If we can't get the checksum for the secondary location, we assume
431 // the dex checksum is up to date for this and all other secondary dex
432 // files.
433 break;
434 }
435 }
436
437 // Verify the image checksum
438 const ImageInfo* image_info = GetImageInfo();
439 if (image_info == nullptr) {
440 VLOG(oat) << "No image for oat image checksum to match against.";
441 return true;
442 }
443
444 if (file.GetOatHeader().GetImageFileLocationOatChecksum() != image_info->oat_checksum) {
445 VLOG(oat) << "Oat image checksum does not match image checksum.";
446 return true;
447 }
448
449 // The checksums are all good; the dex file is not out of date.
450 return false;
451}
452
453bool OatFileAssistant::GivenOatFileNeedsRelocation(const OatFile& file) {
Richard Uhler95abd042015-03-24 09:51:28 -0700454 return GivenOatFileStatus(file) == kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800455}
456
457bool OatFileAssistant::GivenOatFileIsUpToDate(const OatFile& file) {
458 if (GivenOatFileIsOutOfDate(file)) {
459 return false;
460 }
461
462 if (file.IsPic()) {
463 return true;
464 }
465
466 const ImageInfo* image_info = GetImageInfo();
467 if (image_info == nullptr) {
468 VLOG(oat) << "No image for to check oat relocation against.";
469 return false;
470 }
471
472 // Verify the oat_data_begin recorded for the image in the oat file matches
473 // the actual oat_data_begin for boot.oat in the image.
474 const OatHeader& oat_header = file.GetOatHeader();
475 uintptr_t oat_data_begin = oat_header.GetImageFileLocationOatDataBegin();
476 if (oat_data_begin != image_info->oat_data_begin) {
477 VLOG(oat) << file.GetLocation() <<
478 ": Oat file image oat_data_begin (" << oat_data_begin << ")"
479 << " does not match actual image oat_data_begin ("
480 << image_info->oat_data_begin << ")";
481 return false;
482 }
483
484 // Verify the oat_patch_delta recorded for the image in the oat file matches
485 // the actual oat_patch_delta for the image.
486 int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
487 if (oat_patch_delta != image_info->patch_delta) {
488 VLOG(oat) << file.GetLocation() <<
489 ": Oat file image patch delta (" << oat_patch_delta << ")"
490 << " does not match actual image patch delta ("
491 << image_info->patch_delta << ")";
492 return false;
493 }
494 return true;
495}
496
497bool OatFileAssistant::ProfileExists() {
498 return GetProfile() != nullptr;
499}
500
501bool OatFileAssistant::OldProfileExists() {
502 return GetOldProfile() != nullptr;
503}
504
505// TODO: The IsProfileChangeSignificant implementation was copied from likely
506// bit-rotted code.
507bool OatFileAssistant::IsProfileChangeSignificant() {
508 ProfileFile* profile = GetProfile();
509 if (profile == nullptr) {
510 return false;
511 }
512
513 ProfileFile* old_profile = GetOldProfile();
514 if (old_profile == nullptr) {
515 return false;
516 }
517
518 // TODO: The following code to compare two profile files should live with
519 // the rest of the profiler code, not the oat file assistant code.
520
521 // A change in profile is considered significant if X% (change_thr property)
522 // of the top K% (compile_thr property) samples has changed.
523 const ProfilerOptions& options = Runtime::Current()->GetProfilerOptions();
524 const double top_k_threshold = options.GetTopKThreshold();
525 const double change_threshold = options.GetTopKChangeThreshold();
526 std::set<std::string> top_k, old_top_k;
527 profile->GetTopKSamples(top_k, top_k_threshold);
528 old_profile->GetTopKSamples(old_top_k, top_k_threshold);
529 std::set<std::string> diff;
530 std::set_difference(top_k.begin(), top_k.end(), old_top_k.begin(),
531 old_top_k.end(), std::inserter(diff, diff.end()));
532
533 // TODO: consider using the usedPercentage instead of the plain diff count.
534 double change_percent = 100.0 * static_cast<double>(diff.size())
535 / static_cast<double>(top_k.size());
536 std::set<std::string>::iterator end = diff.end();
537 for (std::set<std::string>::iterator it = diff.begin(); it != end; it++) {
538 VLOG(oat) << "Profile new in topK: " << *it;
539 }
540
541 if (change_percent > change_threshold) {
542 VLOG(oat) << "Oat File Assistant: Profile for " << dex_location_
543 << "has changed significantly: (top "
544 << top_k_threshold << "% samples changed in proportion of "
545 << change_percent << "%)";
546 return true;
547 }
548 return false;
549}
550
551// TODO: The CopyProfileFile implementation was copied from likely bit-rotted
552// code.
553void OatFileAssistant::CopyProfileFile() {
554 if (!ProfileExists()) {
555 return;
556 }
557
558 std::string profile_name = ProfileFileName();
559 std::string old_profile_name = OldProfileFileName();
560
561 ScopedFd src(open(old_profile_name.c_str(), O_RDONLY));
562 if (src.get() == -1) {
563 PLOG(WARNING) << "Failed to open profile file " << old_profile_name
564 << ". My uid:gid is " << getuid() << ":" << getgid();
565 return;
566 }
567
568 struct stat stat_src;
569 if (fstat(src.get(), &stat_src) == -1) {
570 PLOG(WARNING) << "Failed to get stats for profile file " << old_profile_name
571 << ". My uid:gid is " << getuid() << ":" << getgid();
572 return;
573 }
574
575 // Create the copy with rw------- (only accessible by system)
576 ScopedFd dst(open(profile_name.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0600));
577 if (dst.get() == -1) {
578 PLOG(WARNING) << "Failed to create/write prev profile file " << profile_name
579 << ". My uid:gid is " << getuid() << ":" << getgid();
580 return;
581 }
582
583#ifdef __linux__
584 if (sendfile(dst.get(), src.get(), nullptr, stat_src.st_size) == -1) {
585#else
586 off_t len;
587 if (sendfile(dst.get(), src.get(), 0, &len, nullptr, 0) == -1) {
588#endif
589 PLOG(WARNING) << "Failed to copy profile file " << old_profile_name
590 << " to " << profile_name << ". My uid:gid is " << getuid()
591 << ":" << getgid();
592 }
593}
594
Richard Uhler95abd042015-03-24 09:51:28 -0700595bool OatFileAssistant::RelocateOatFile(const std::string* input_file,
596 std::string* error_msg) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800597 CHECK(error_msg != nullptr);
598
Richard Uhler95abd042015-03-24 09:51:28 -0700599 if (input_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800600 *error_msg = "Patching of oat file for dex location "
601 + std::string(dex_location_)
Richard Uhler95abd042015-03-24 09:51:28 -0700602 + " not attempted because the input file name could not be determined.";
Richard Uhler66d874d2015-01-15 09:37:19 -0800603 return false;
604 }
Richard Uhler95abd042015-03-24 09:51:28 -0700605 const std::string& input_file_name = *input_file;
Richard Uhler66d874d2015-01-15 09:37:19 -0800606
607 if (OatFileName() == nullptr) {
608 *error_msg = "Patching of oat file for dex location "
609 + std::string(dex_location_)
610 + " not attempted because the oat file name could not be determined.";
611 return false;
612 }
613 const std::string& oat_file_name = *OatFileName();
614
615 const ImageInfo* image_info = GetImageInfo();
616 Runtime* runtime = Runtime::Current();
617 if (image_info == nullptr) {
618 *error_msg = "Patching of oat file " + oat_file_name
619 + " not attempted because no image location was found.";
620 return false;
621 }
622
623 if (!runtime->IsDex2OatEnabled()) {
624 *error_msg = "Patching of oat file " + oat_file_name
625 + " not attempted because dex2oat is disabled";
626 return false;
627 }
628
629 std::vector<std::string> argv;
630 argv.push_back(runtime->GetPatchoatExecutable());
631 argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(isa_)));
Richard Uhler95abd042015-03-24 09:51:28 -0700632 argv.push_back("--input-oat-file=" + input_file_name);
Richard Uhler66d874d2015-01-15 09:37:19 -0800633 argv.push_back("--output-oat-file=" + oat_file_name);
634 argv.push_back("--patched-image-location=" + image_info->location);
635
636 std::string command_line(Join(argv, ' '));
637 if (!Exec(argv, error_msg)) {
638 // Manually delete the file. This ensures there is no garbage left over if
639 // the process unexpectedly died.
640 TEMP_FAILURE_RETRY(unlink(oat_file_name.c_str()));
641 return false;
642 }
643
644 // Mark that the oat file has changed and we should try to reload.
645 ClearOatFileCache();
646 return true;
647}
648
649bool OatFileAssistant::GenerateOatFile(std::string* error_msg) {
650 CHECK(error_msg != nullptr);
651
652 if (OatFileName() == nullptr) {
653 *error_msg = "Generation of oat file for dex location "
654 + std::string(dex_location_)
655 + " not attempted because the oat file name could not be determined.";
656 return false;
657 }
658 const std::string& oat_file_name = *OatFileName();
659
660 Runtime* runtime = Runtime::Current();
661 if (!runtime->IsDex2OatEnabled()) {
662 *error_msg = "Generation of oat file " + oat_file_name
663 + " not attempted because dex2oat is disabled";
664 return false;
665 }
666
667 std::vector<std::string> args;
668 args.push_back("--dex-file=" + std::string(dex_location_));
669 args.push_back("--oat-file=" + oat_file_name);
670
671 // dex2oat ignores missing dex files and doesn't report an error.
672 // Check explicitly here so we can detect the error properly.
673 // TODO: Why does dex2oat behave that way?
674 if (!OS::FileExists(dex_location_)) {
675 *error_msg = "Dex location " + std::string(dex_location_) + " does not exists.";
676 return false;
677 }
678
679 if (!Dex2Oat(args, error_msg)) {
680 // Manually delete the file. This ensures there is no garbage left over if
681 // the process unexpectedly died.
682 TEMP_FAILURE_RETRY(unlink(oat_file_name.c_str()));
683 return false;
684 }
685
686 // Mark that the oat file has changed and we should try to reload.
687 ClearOatFileCache();
688 return true;
689}
690
691bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args,
692 std::string* error_msg) {
693 Runtime* runtime = Runtime::Current();
694 std::string image_location = ImageLocation();
695 if (image_location.empty()) {
696 *error_msg = "No image location found for Dex2Oat.";
697 return false;
698 }
699
700 std::vector<std::string> argv;
701 argv.push_back(runtime->GetCompilerExecutable());
702 argv.push_back("--runtime-arg");
703 argv.push_back("-classpath");
704 argv.push_back("--runtime-arg");
705 argv.push_back(runtime->GetClassPathString());
706 runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
707
708 if (!runtime->IsVerificationEnabled()) {
709 argv.push_back("--compiler-filter=verify-none");
710 }
711
712 if (runtime->MustRelocateIfPossible()) {
713 argv.push_back("--runtime-arg");
714 argv.push_back("-Xrelocate");
715 } else {
716 argv.push_back("--runtime-arg");
717 argv.push_back("-Xnorelocate");
718 }
719
720 if (!kIsTargetBuild) {
721 argv.push_back("--host");
722 }
723
724 argv.push_back("--boot-image=" + image_location);
725
726 std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
727 argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
728
729 argv.insert(argv.end(), args.begin(), args.end());
730
731 std::string command_line(Join(argv, ' '));
732 return Exec(argv, error_msg);
733}
734
735bool OatFileAssistant::DexFilenameToOdexFilename(const std::string& location,
736 InstructionSet isa, std::string* odex_filename, std::string* error_msg) {
737 CHECK(odex_filename != nullptr);
738 CHECK(error_msg != nullptr);
739
740 // The odex file name is formed by replacing the dex_location extension with
Richard Uhler63434112015-03-16 14:32:16 -0700741 // .odex and inserting an oat/<isa> directory. For example:
Richard Uhler66d874d2015-01-15 09:37:19 -0800742 // location = /foo/bar/baz.jar
Richard Uhler63434112015-03-16 14:32:16 -0700743 // odex_location = /foo/bar/oat/<isa>/baz.odex
Richard Uhler66d874d2015-01-15 09:37:19 -0800744
Richard Uhler63434112015-03-16 14:32:16 -0700745 // Find the directory portion of the dex location and add the oat/<isa>
746 // directory.
Richard Uhler66d874d2015-01-15 09:37:19 -0800747 size_t pos = location.rfind('/');
748 if (pos == std::string::npos) {
749 *error_msg = "Dex location " + location + " has no directory.";
750 return false;
751 }
752 std::string dir = location.substr(0, pos+1);
Richard Uhler63434112015-03-16 14:32:16 -0700753 dir += "oat/" + std::string(GetInstructionSetString(isa));
Richard Uhler66d874d2015-01-15 09:37:19 -0800754
755 // Find the file portion of the dex location.
756 std::string file;
757 if (pos == std::string::npos) {
758 file = location;
759 } else {
760 file = location.substr(pos+1);
761 }
762
763 // Get the base part of the file without the extension.
764 pos = file.rfind('.');
765 if (pos == std::string::npos) {
766 *error_msg = "Dex location " + location + " has no extension.";
767 return false;
768 }
769 std::string base = file.substr(0, pos);
770
771 *odex_filename = dir + "/" + base + ".odex";
772 return true;
773}
774
775std::string OatFileAssistant::DalvikCacheDirectory() {
776 // Note: We don't cache this, because it will only be called once by
777 // OatFileName, and we don't care about the performance of the profiling
778 // code, which isn't used in practice.
779
780 // TODO: The work done in GetDalvikCache is overkill for what we need.
781 // Ideally a new API for getting the DalvikCacheDirectory the way we want
782 // (without existence testing, creation, or death) is provided with the rest
783 // of the GetDalvikCache family of functions. Until such an API is in place,
784 // we use GetDalvikCache to avoid duplicating the logic for determining the
785 // dalvik cache directory.
786 std::string result;
787 bool have_android_data;
788 bool dalvik_cache_exists;
789 bool is_global_cache;
790 GetDalvikCache("", false, &result, &have_android_data, &dalvik_cache_exists, &is_global_cache);
791 return result;
792}
793
794std::string OatFileAssistant::ProfileFileName() {
795 if (package_name_ != nullptr) {
796 return DalvikCacheDirectory() + std::string("profiles/") + package_name_;
797 }
798 return "";
799}
800
801std::string OatFileAssistant::OldProfileFileName() {
802 std::string profile_name = ProfileFileName();
803 if (profile_name.empty()) {
804 return "";
805 }
806 return profile_name + "@old";
807}
808
809std::string OatFileAssistant::ImageLocation() {
810 Runtime* runtime = Runtime::Current();
811 const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace();
812 if (image_space == nullptr) {
813 return "";
814 }
815 return image_space->GetImageLocation();
816}
817
818const uint32_t* OatFileAssistant::GetRequiredDexChecksum() {
819 if (!required_dex_checksum_attempted) {
820 required_dex_checksum_attempted = true;
821 required_dex_checksum_found = false;
822 std::string error_msg;
823 CHECK(dex_location_ != nullptr) << "OatFileAssistant provided no dex location";
824 if (DexFile::GetChecksum(dex_location_, &cached_required_dex_checksum, &error_msg)) {
825 required_dex_checksum_found = true;
826 } else {
827 // This can happen if the original dex file has been stripped from the
828 // apk.
829 VLOG(oat) << "OatFileAssistant: " << error_msg;
830
831 // Get the checksum from the odex if we can.
832 const OatFile* odex_file = GetOdexFile();
833 if (odex_file != nullptr) {
834 const OatFile::OatDexFile* odex_dex_file = odex_file->GetOatDexFile(
835 dex_location_, nullptr, false);
836 if (odex_dex_file != nullptr) {
837 cached_required_dex_checksum = odex_dex_file->GetDexFileLocationChecksum();
838 required_dex_checksum_found = true;
839 }
840 }
841 }
842 }
843 return required_dex_checksum_found ? &cached_required_dex_checksum : nullptr;
844}
845
846const OatFile* OatFileAssistant::GetOdexFile() {
847 CHECK(!oat_file_released_) << "OdexFile called after oat file released.";
848 if (!odex_file_load_attempted_) {
849 odex_file_load_attempted_ = true;
850 if (OdexFileName() != nullptr) {
851 const std::string& odex_file_name = *OdexFileName();
852 std::string error_msg;
853 cached_odex_file_.reset(OatFile::Open(odex_file_name.c_str(),
854 odex_file_name.c_str(), nullptr, nullptr, load_executable_,
Richard Uhlere5fed032015-03-18 08:21:11 -0700855 dex_location_, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -0800856 if (cached_odex_file_.get() == nullptr) {
857 VLOG(oat) << "OatFileAssistant test for existing pre-compiled oat file "
858 << odex_file_name << ": " << error_msg;
859 }
860 }
861 }
862 return cached_odex_file_.get();
863}
864
865void OatFileAssistant::ClearOdexFileCache() {
866 odex_file_load_attempted_ = false;
867 cached_odex_file_.reset();
868 odex_file_is_out_of_date_attempted_ = false;
869 odex_file_is_up_to_date_attempted_ = false;
870}
871
872const OatFile* OatFileAssistant::GetOatFile() {
873 CHECK(!oat_file_released_) << "OatFile called after oat file released.";
874 if (!oat_file_load_attempted_) {
875 oat_file_load_attempted_ = true;
876 if (OatFileName() != nullptr) {
877 const std::string& oat_file_name = *OatFileName();
878 std::string error_msg;
879 cached_oat_file_.reset(OatFile::Open(oat_file_name.c_str(),
Richard Uhlere5fed032015-03-18 08:21:11 -0700880 oat_file_name.c_str(), nullptr, nullptr, load_executable_,
881 dex_location_, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -0800882 if (cached_oat_file_.get() == nullptr) {
883 VLOG(oat) << "OatFileAssistant test for existing oat file "
884 << oat_file_name << ": " << error_msg;
885 }
886 }
887 }
888 return cached_oat_file_.get();
889}
890
891void OatFileAssistant::ClearOatFileCache() {
892 oat_file_load_attempted_ = false;
893 cached_oat_file_.reset();
894 oat_file_is_out_of_date_attempted_ = false;
895 oat_file_is_up_to_date_attempted_ = false;
896}
897
898const OatFileAssistant::ImageInfo* OatFileAssistant::GetImageInfo() {
899 if (!image_info_load_attempted_) {
900 image_info_load_attempted_ = true;
901
902 Runtime* runtime = Runtime::Current();
903 const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace();
904 if (image_space != nullptr) {
905 cached_image_info_.location = image_space->GetImageLocation();
906
907 if (isa_ == kRuntimeISA) {
908 const ImageHeader& image_header = image_space->GetImageHeader();
909 cached_image_info_.oat_checksum = image_header.GetOatChecksum();
910 cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin());
911 cached_image_info_.patch_delta = image_header.GetPatchDelta();
912 } else {
913 std::unique_ptr<ImageHeader> image_header(
914 gc::space::ImageSpace::ReadImageHeaderOrDie(
915 cached_image_info_.location.c_str(), isa_));
916 cached_image_info_.oat_checksum = image_header->GetOatChecksum();
917 cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin());
918 cached_image_info_.patch_delta = image_header->GetPatchDelta();
919 }
920 }
921 image_info_load_succeeded_ = (image_space != nullptr);
922 }
923 return image_info_load_succeeded_ ? &cached_image_info_ : nullptr;
924}
925
926ProfileFile* OatFileAssistant::GetProfile() {
927 if (!profile_load_attempted_) {
928 CHECK(package_name_ != nullptr)
929 << "pakage_name_ is nullptr: "
930 << "profile_load_attempted_ should have been true";
931 profile_load_attempted_ = true;
932 std::string profile_name = ProfileFileName();
933 if (!profile_name.empty()) {
934 profile_load_succeeded_ = cached_profile_.LoadFile(profile_name);
935 }
936 }
937 return profile_load_succeeded_ ? &cached_profile_ : nullptr;
938}
939
940ProfileFile* OatFileAssistant::GetOldProfile() {
941 if (!old_profile_load_attempted_) {
942 CHECK(package_name_ != nullptr)
943 << "pakage_name_ is nullptr: "
944 << "old_profile_load_attempted_ should have been true";
945 old_profile_load_attempted_ = true;
946 std::string old_profile_name = OldProfileFileName();
947 if (!old_profile_name.empty()) {
948 old_profile_load_succeeded_ = cached_old_profile_.LoadFile(old_profile_name);
949 }
950 }
951 return old_profile_load_succeeded_ ? &cached_old_profile_ : nullptr;
952}
953
954} // namespace art
955