blob: 29b879ee80013fce04abe4d55ff1d0e4524a4de5 [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.
Richard Uhler581f4e92015-05-07 10:19:35 -070099 if (flock_.HasFile()) {
100 TEMP_FAILURE_RETRY(unlink(flock_.GetFile()->GetPath().c_str()));
Richard Uhler66d874d2015-01-15 09:37:19 -0800101 }
102}
103
104bool OatFileAssistant::IsInBootClassPath() {
105 // Note: We check the current boot class path, regardless of the ISA
106 // specified by the user. This is okay, because the boot class path should
107 // be the same for all ISAs.
108 // TODO: Can we verify the boot class path is the same for all ISAs?
109 Runtime* runtime = Runtime::Current();
110 ClassLinker* class_linker = runtime->GetClassLinker();
111 const auto& boot_class_path = class_linker->GetBootClassPath();
112 for (size_t i = 0; i < boot_class_path.size(); i++) {
113 if (boot_class_path[i]->GetLocation() == std::string(dex_location_)) {
114 VLOG(oat) << "Dex location " << dex_location_ << " is in boot class path";
115 return true;
116 }
117 }
118 return false;
119}
120
121bool OatFileAssistant::Lock(std::string* error_msg) {
122 CHECK(error_msg != nullptr);
Richard Uhler581f4e92015-05-07 10:19:35 -0700123 CHECK(!flock_.HasFile()) << "OatFileAssistant::Lock already acquired";
Richard Uhler66d874d2015-01-15 09:37:19 -0800124
125 if (OatFileName() == nullptr) {
126 *error_msg = "Failed to determine lock file";
127 return false;
128 }
129 std::string lock_file_name = *OatFileName() + ".flock";
130
Richard Uhler581f4e92015-05-07 10:19:35 -0700131 if (!flock_.Init(lock_file_name.c_str(), error_msg)) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800132 TEMP_FAILURE_RETRY(unlink(lock_file_name.c_str()));
133 return false;
134 }
135 return true;
136}
137
Richard Uhler95abd042015-03-24 09:51:28 -0700138OatFileAssistant::DexOptNeeded OatFileAssistant::GetDexOptNeeded() {
Richard Uhler66d874d2015-01-15 09:37:19 -0800139 // TODO: If the profiling code is ever restored, it's worth considering
140 // whether we should check to see if the profile is out of date here.
141
Richard Uhler95abd042015-03-24 09:51:28 -0700142 if (OatFileIsUpToDate() || OdexFileIsUpToDate()) {
143 return kNoDexOptNeeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800144 }
Richard Uhler95abd042015-03-24 09:51:28 -0700145
146 if (OdexFileNeedsRelocation()) {
147 return kPatchOatNeeded;
148 }
149
150 if (OatFileNeedsRelocation()) {
151 return kSelfPatchOatNeeded;
152 }
153
Richard Uhler9b994ea2015-06-24 08:44:19 -0700154 return HasOriginalDexFiles() ? kDex2OatNeeded : kNoDexOptNeeded;
Richard Uhler66d874d2015-01-15 09:37:19 -0800155}
156
157bool OatFileAssistant::MakeUpToDate(std::string* error_msg) {
Richard Uhler95abd042015-03-24 09:51:28 -0700158 switch (GetDexOptNeeded()) {
159 case kNoDexOptNeeded: return true;
160 case kDex2OatNeeded: return GenerateOatFile(error_msg);
161 case kPatchOatNeeded: return RelocateOatFile(OdexFileName(), error_msg);
162 case kSelfPatchOatNeeded: return RelocateOatFile(OatFileName(), error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800163 }
164 UNREACHABLE();
165}
166
167std::unique_ptr<OatFile> OatFileAssistant::GetBestOatFile() {
Richard Uhler5f946da2015-07-17 12:28:32 -0700168 // The best oat files are, in descending order of bestness:
169 // 1. Properly relocated files. These may be opened executable.
170 // 2. Not out-of-date files that are already opened non-executable.
171 // 3. Not out-of-date files that we must reopen non-executable.
172
Richard Uhler66d874d2015-01-15 09:37:19 -0800173 if (OatFileIsUpToDate()) {
174 oat_file_released_ = true;
175 return std::move(cached_oat_file_);
176 }
177
178 if (OdexFileIsUpToDate()) {
179 oat_file_released_ = true;
180 return std::move(cached_odex_file_);
181 }
182
Richard Uhler5f946da2015-07-17 12:28:32 -0700183 VLOG(oat) << "Oat File Assistant: No relocated oat file found,"
184 << " attempting to fall back to interpreting oat file instead.";
Richard Uhler66d874d2015-01-15 09:37:19 -0800185
Richard Uhler5f946da2015-07-17 12:28:32 -0700186 if (!OatFileIsOutOfDate() && !OatFileIsExecutable()) {
187 oat_file_released_ = true;
188 return std::move(cached_oat_file_);
189 }
190
191 if (!OdexFileIsOutOfDate() && !OdexFileIsExecutable()) {
192 oat_file_released_ = true;
193 return std::move(cached_odex_file_);
194 }
195
196 if (!OatFileIsOutOfDate()) {
197 load_executable_ = false;
198 ClearOatFileCache();
Richard Uhler66d874d2015-01-15 09:37:19 -0800199 if (!OatFileIsOutOfDate()) {
Richard Uhler5f946da2015-07-17 12:28:32 -0700200 CHECK(!OatFileIsExecutable());
201 oat_file_released_ = true;
202 return std::move(cached_oat_file_);
Richard Uhler66d874d2015-01-15 09:37:19 -0800203 }
Richard Uhler5f946da2015-07-17 12:28:32 -0700204 }
Richard Uhler66d874d2015-01-15 09:37:19 -0800205
Richard Uhler5f946da2015-07-17 12:28:32 -0700206 if (!OdexFileIsOutOfDate()) {
207 load_executable_ = false;
208 ClearOdexFileCache();
Richard Uhler66d874d2015-01-15 09:37:19 -0800209 if (!OdexFileIsOutOfDate()) {
Richard Uhler5f946da2015-07-17 12:28:32 -0700210 CHECK(!OdexFileIsExecutable());
211 oat_file_released_ = true;
212 return std::move(cached_odex_file_);
Richard Uhler66d874d2015-01-15 09:37:19 -0800213 }
214 }
215
216 return std::unique_ptr<OatFile>();
217}
218
219std::vector<std::unique_ptr<const DexFile>> OatFileAssistant::LoadDexFiles(
220 const OatFile& oat_file, const char* dex_location) {
221 std::vector<std::unique_ptr<const DexFile>> dex_files;
222
223 // Load the primary dex file.
224 std::string error_msg;
225 const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(
226 dex_location, nullptr, false);
227 if (oat_dex_file == nullptr) {
228 LOG(WARNING) << "Attempt to load out-of-date oat file "
229 << oat_file.GetLocation() << " for dex location " << dex_location;
230 return std::vector<std::unique_ptr<const DexFile>>();
231 }
232
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700233 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800234 if (dex_file.get() == nullptr) {
235 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
236 return std::vector<std::unique_ptr<const DexFile>>();
237 }
238 dex_files.push_back(std::move(dex_file));
239
240 // Load secondary multidex files
Andreas Gampe90e34042015-04-27 20:01:52 -0700241 for (size_t i = 1; ; i++) {
242 std::string secondary_dex_location = DexFile::GetMultiDexLocation(i, dex_location);
Richard Uhler66d874d2015-01-15 09:37:19 -0800243 oat_dex_file = oat_file.GetOatDexFile(secondary_dex_location.c_str(), nullptr, false);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700244 if (oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800245 // There are no more secondary dex files to load.
246 break;
247 }
248
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700249 dex_file = oat_dex_file->OpenDexFile(&error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800250 if (dex_file.get() == nullptr) {
251 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
252 return std::vector<std::unique_ptr<const DexFile>>();
253 }
254 dex_files.push_back(std::move(dex_file));
255 }
256 return dex_files;
257}
258
Richard Uhler9b994ea2015-06-24 08:44:19 -0700259bool OatFileAssistant::HasOriginalDexFiles() {
260 // Ensure GetRequiredDexChecksum has been run so that
261 // has_original_dex_files_ is initialized. We don't care about the result of
262 // GetRequiredDexChecksum.
263 GetRequiredDexChecksum();
264 return has_original_dex_files_;
265}
266
Richard Uhler66d874d2015-01-15 09:37:19 -0800267const std::string* OatFileAssistant::OdexFileName() {
268 if (!cached_odex_file_name_attempted_) {
269 CHECK(dex_location_ != nullptr) << "OatFileAssistant: null dex location";
270 cached_odex_file_name_attempted_ = true;
271
272 std::string error_msg;
273 cached_odex_file_name_found_ = DexFilenameToOdexFilename(
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700274 dex_location_, isa_, &cached_odex_file_name_, &error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800275 if (!cached_odex_file_name_found_) {
276 // If we can't figure out the odex file, we treat it as if the odex
277 // file was inaccessible.
278 LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
279 }
280 }
281 return cached_odex_file_name_found_ ? &cached_odex_file_name_ : nullptr;
282}
283
284bool OatFileAssistant::OdexFileExists() {
285 return GetOdexFile() != nullptr;
286}
287
Richard Uhler95abd042015-03-24 09:51:28 -0700288OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() {
Richard Uhler66d874d2015-01-15 09:37:19 -0800289 if (OdexFileIsOutOfDate()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700290 return kOatOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800291 }
292 if (OdexFileIsUpToDate()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700293 return kOatUpToDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800294 }
Richard Uhler95abd042015-03-24 09:51:28 -0700295 return kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800296}
297
298bool OatFileAssistant::OdexFileIsOutOfDate() {
299 if (!odex_file_is_out_of_date_attempted_) {
300 odex_file_is_out_of_date_attempted_ = true;
301 const OatFile* odex_file = GetOdexFile();
302 if (odex_file == nullptr) {
303 cached_odex_file_is_out_of_date_ = true;
304 } else {
305 cached_odex_file_is_out_of_date_ = GivenOatFileIsOutOfDate(*odex_file);
306 }
307 }
308 return cached_odex_file_is_out_of_date_;
309}
310
311bool OatFileAssistant::OdexFileNeedsRelocation() {
Richard Uhler95abd042015-03-24 09:51:28 -0700312 return OdexFileStatus() == kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800313}
314
315bool OatFileAssistant::OdexFileIsUpToDate() {
316 if (!odex_file_is_up_to_date_attempted_) {
317 odex_file_is_up_to_date_attempted_ = true;
318 const OatFile* odex_file = GetOdexFile();
319 if (odex_file == nullptr) {
320 cached_odex_file_is_up_to_date_ = false;
321 } else {
322 cached_odex_file_is_up_to_date_ = GivenOatFileIsUpToDate(*odex_file);
323 }
324 }
325 return cached_odex_file_is_up_to_date_;
326}
327
328const std::string* OatFileAssistant::OatFileName() {
329 if (!cached_oat_file_name_attempted_) {
330 cached_oat_file_name_attempted_ = true;
331
332 // Compute the oat file name from the dex location.
333 CHECK(dex_location_ != nullptr) << "OatFileAssistant: null dex location";
334
335 // TODO: The oat file assistant should be the definitive place for
336 // determining the oat file name from the dex location, not
337 // GetDalvikCacheFilename.
338 std::string cache_dir = StringPrintf("%s%s",
339 DalvikCacheDirectory().c_str(), GetInstructionSetString(isa_));
340 std::string error_msg;
341 cached_oat_file_name_found_ = GetDalvikCacheFilename(dex_location_,
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700342 cache_dir.c_str(), &cached_oat_file_name_, &error_msg);
Richard Uhler66d874d2015-01-15 09:37:19 -0800343 if (!cached_oat_file_name_found_) {
344 // If we can't determine the oat file name, we treat the oat file as
345 // inaccessible.
346 LOG(WARNING) << "Failed to determine oat file name for dex location "
347 << dex_location_ << ": " << error_msg;
348 }
349 }
350 return cached_oat_file_name_found_ ? &cached_oat_file_name_ : nullptr;
351}
352
353bool OatFileAssistant::OatFileExists() {
354 return GetOatFile() != nullptr;
355}
356
Richard Uhler95abd042015-03-24 09:51:28 -0700357OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() {
Richard Uhler66d874d2015-01-15 09:37:19 -0800358 if (OatFileIsOutOfDate()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700359 return kOatOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800360 }
361 if (OatFileIsUpToDate()) {
Richard Uhler95abd042015-03-24 09:51:28 -0700362 return kOatUpToDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800363 }
Richard Uhler95abd042015-03-24 09:51:28 -0700364 return kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800365}
366
367bool OatFileAssistant::OatFileIsOutOfDate() {
368 if (!oat_file_is_out_of_date_attempted_) {
369 oat_file_is_out_of_date_attempted_ = true;
370 const OatFile* oat_file = GetOatFile();
371 if (oat_file == nullptr) {
372 cached_oat_file_is_out_of_date_ = true;
373 } else {
374 cached_oat_file_is_out_of_date_ = GivenOatFileIsOutOfDate(*oat_file);
375 }
376 }
377 return cached_oat_file_is_out_of_date_;
378}
379
380bool OatFileAssistant::OatFileNeedsRelocation() {
Richard Uhler95abd042015-03-24 09:51:28 -0700381 return OatFileStatus() == kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800382}
383
384bool OatFileAssistant::OatFileIsUpToDate() {
385 if (!oat_file_is_up_to_date_attempted_) {
386 oat_file_is_up_to_date_attempted_ = true;
387 const OatFile* oat_file = GetOatFile();
388 if (oat_file == nullptr) {
389 cached_oat_file_is_up_to_date_ = false;
390 } else {
391 cached_oat_file_is_up_to_date_ = GivenOatFileIsUpToDate(*oat_file);
392 }
393 }
394 return cached_oat_file_is_up_to_date_;
395}
396
Richard Uhler95abd042015-03-24 09:51:28 -0700397OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800398 // TODO: This could cause GivenOatFileIsOutOfDate to be called twice, which
399 // is more work than we need to do. If performance becomes a concern, and
400 // this method is actually called, this should be fixed.
401 if (GivenOatFileIsOutOfDate(file)) {
Richard Uhler95abd042015-03-24 09:51:28 -0700402 return kOatOutOfDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800403 }
404 if (GivenOatFileIsUpToDate(file)) {
Richard Uhler95abd042015-03-24 09:51:28 -0700405 return kOatUpToDate;
Richard Uhler66d874d2015-01-15 09:37:19 -0800406 }
Richard Uhler95abd042015-03-24 09:51:28 -0700407 return kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800408}
409
410bool OatFileAssistant::GivenOatFileIsOutOfDate(const OatFile& file) {
411 // Verify the dex checksum.
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700412 // Note: GetOatDexFile will return null if the dex checksum doesn't match
Richard Uhler66d874d2015-01-15 09:37:19 -0800413 // what we provide, which verifies the primary dex checksum for us.
414 const uint32_t* dex_checksum_pointer = GetRequiredDexChecksum();
415 const OatFile::OatDexFile* oat_dex_file = file.GetOatDexFile(
416 dex_location_, dex_checksum_pointer, false);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700417 if (oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800418 return true;
419 }
420
421 // Verify the dex checksums for any secondary multidex files
Andreas Gampe90e34042015-04-27 20:01:52 -0700422 for (size_t i = 1; ; i++) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800423 std::string secondary_dex_location
Andreas Gampe90e34042015-04-27 20:01:52 -0700424 = DexFile::GetMultiDexLocation(i, dex_location_);
Richard Uhler66d874d2015-01-15 09:37:19 -0800425 const OatFile::OatDexFile* secondary_oat_dex_file
426 = file.GetOatDexFile(secondary_dex_location.c_str(), nullptr, false);
Mathieu Chartier2cebb242015-04-21 16:50:40 -0700427 if (secondary_oat_dex_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800428 // There are no more secondary dex files to check.
429 break;
430 }
431
432 std::string error_msg;
433 uint32_t expected_secondary_checksum = 0;
434 if (DexFile::GetChecksum(secondary_dex_location.c_str(),
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700435 &expected_secondary_checksum, &error_msg)) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800436 uint32_t actual_secondary_checksum
437 = secondary_oat_dex_file->GetDexFileLocationChecksum();
438 if (expected_secondary_checksum != actual_secondary_checksum) {
439 VLOG(oat) << "Dex checksum does not match for secondary dex: "
440 << secondary_dex_location
441 << ". Expected: " << expected_secondary_checksum
442 << ", Actual: " << actual_secondary_checksum;
Richard Uhler67ff7d12015-05-14 13:21:13 -0700443 return true;
Richard Uhler66d874d2015-01-15 09:37:19 -0800444 }
445 } else {
446 // If we can't get the checksum for the secondary location, we assume
447 // the dex checksum is up to date for this and all other secondary dex
448 // files.
449 break;
450 }
451 }
452
453 // Verify the image checksum
454 const ImageInfo* image_info = GetImageInfo();
455 if (image_info == nullptr) {
456 VLOG(oat) << "No image for oat image checksum to match against.";
457 return true;
458 }
459
460 if (file.GetOatHeader().GetImageFileLocationOatChecksum() != image_info->oat_checksum) {
461 VLOG(oat) << "Oat image checksum does not match image checksum.";
462 return true;
463 }
464
465 // The checksums are all good; the dex file is not out of date.
466 return false;
467}
468
469bool OatFileAssistant::GivenOatFileNeedsRelocation(const OatFile& file) {
Richard Uhler95abd042015-03-24 09:51:28 -0700470 return GivenOatFileStatus(file) == kOatNeedsRelocation;
Richard Uhler66d874d2015-01-15 09:37:19 -0800471}
472
473bool OatFileAssistant::GivenOatFileIsUpToDate(const OatFile& file) {
474 if (GivenOatFileIsOutOfDate(file)) {
475 return false;
476 }
477
478 if (file.IsPic()) {
479 return true;
480 }
481
482 const ImageInfo* image_info = GetImageInfo();
483 if (image_info == nullptr) {
Richard Uhlerf7f798c2015-05-11 09:36:57 -0700484 VLOG(oat) << "No image to check oat relocation against.";
Richard Uhler66d874d2015-01-15 09:37:19 -0800485 return false;
486 }
487
488 // Verify the oat_data_begin recorded for the image in the oat file matches
489 // the actual oat_data_begin for boot.oat in the image.
490 const OatHeader& oat_header = file.GetOatHeader();
491 uintptr_t oat_data_begin = oat_header.GetImageFileLocationOatDataBegin();
492 if (oat_data_begin != image_info->oat_data_begin) {
493 VLOG(oat) << file.GetLocation() <<
494 ": Oat file image oat_data_begin (" << oat_data_begin << ")"
495 << " does not match actual image oat_data_begin ("
496 << image_info->oat_data_begin << ")";
497 return false;
498 }
499
500 // Verify the oat_patch_delta recorded for the image in the oat file matches
501 // the actual oat_patch_delta for the image.
502 int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
503 if (oat_patch_delta != image_info->patch_delta) {
504 VLOG(oat) << file.GetLocation() <<
505 ": Oat file image patch delta (" << oat_patch_delta << ")"
506 << " does not match actual image patch delta ("
507 << image_info->patch_delta << ")";
508 return false;
509 }
510 return true;
511}
512
513bool OatFileAssistant::ProfileExists() {
514 return GetProfile() != nullptr;
515}
516
517bool OatFileAssistant::OldProfileExists() {
518 return GetOldProfile() != nullptr;
519}
520
521// TODO: The IsProfileChangeSignificant implementation was copied from likely
522// bit-rotted code.
523bool OatFileAssistant::IsProfileChangeSignificant() {
524 ProfileFile* profile = GetProfile();
525 if (profile == nullptr) {
526 return false;
527 }
528
529 ProfileFile* old_profile = GetOldProfile();
530 if (old_profile == nullptr) {
531 return false;
532 }
533
534 // TODO: The following code to compare two profile files should live with
535 // the rest of the profiler code, not the oat file assistant code.
536
537 // A change in profile is considered significant if X% (change_thr property)
538 // of the top K% (compile_thr property) samples has changed.
539 const ProfilerOptions& options = Runtime::Current()->GetProfilerOptions();
540 const double top_k_threshold = options.GetTopKThreshold();
541 const double change_threshold = options.GetTopKChangeThreshold();
542 std::set<std::string> top_k, old_top_k;
543 profile->GetTopKSamples(top_k, top_k_threshold);
544 old_profile->GetTopKSamples(old_top_k, top_k_threshold);
545 std::set<std::string> diff;
546 std::set_difference(top_k.begin(), top_k.end(), old_top_k.begin(),
547 old_top_k.end(), std::inserter(diff, diff.end()));
548
549 // TODO: consider using the usedPercentage instead of the plain diff count.
550 double change_percent = 100.0 * static_cast<double>(diff.size())
551 / static_cast<double>(top_k.size());
552 std::set<std::string>::iterator end = diff.end();
553 for (std::set<std::string>::iterator it = diff.begin(); it != end; it++) {
554 VLOG(oat) << "Profile new in topK: " << *it;
555 }
556
557 if (change_percent > change_threshold) {
558 VLOG(oat) << "Oat File Assistant: Profile for " << dex_location_
559 << "has changed significantly: (top "
560 << top_k_threshold << "% samples changed in proportion of "
561 << change_percent << "%)";
562 return true;
563 }
564 return false;
565}
566
567// TODO: The CopyProfileFile implementation was copied from likely bit-rotted
568// code.
569void OatFileAssistant::CopyProfileFile() {
570 if (!ProfileExists()) {
571 return;
572 }
573
574 std::string profile_name = ProfileFileName();
575 std::string old_profile_name = OldProfileFileName();
576
577 ScopedFd src(open(old_profile_name.c_str(), O_RDONLY));
578 if (src.get() == -1) {
579 PLOG(WARNING) << "Failed to open profile file " << old_profile_name
580 << ". My uid:gid is " << getuid() << ":" << getgid();
581 return;
582 }
583
584 struct stat stat_src;
585 if (fstat(src.get(), &stat_src) == -1) {
586 PLOG(WARNING) << "Failed to get stats for profile file " << old_profile_name
587 << ". My uid:gid is " << getuid() << ":" << getgid();
588 return;
589 }
590
591 // Create the copy with rw------- (only accessible by system)
592 ScopedFd dst(open(profile_name.c_str(), O_WRONLY|O_CREAT|O_TRUNC, 0600));
593 if (dst.get() == -1) {
594 PLOG(WARNING) << "Failed to create/write prev profile file " << profile_name
595 << ". My uid:gid is " << getuid() << ":" << getgid();
596 return;
597 }
598
599#ifdef __linux__
600 if (sendfile(dst.get(), src.get(), nullptr, stat_src.st_size) == -1) {
601#else
602 off_t len;
603 if (sendfile(dst.get(), src.get(), 0, &len, nullptr, 0) == -1) {
604#endif
605 PLOG(WARNING) << "Failed to copy profile file " << old_profile_name
606 << " to " << profile_name << ". My uid:gid is " << getuid()
607 << ":" << getgid();
608 }
609}
610
Richard Uhler95abd042015-03-24 09:51:28 -0700611bool OatFileAssistant::RelocateOatFile(const std::string* input_file,
612 std::string* error_msg) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800613 CHECK(error_msg != nullptr);
614
Richard Uhler95abd042015-03-24 09:51:28 -0700615 if (input_file == nullptr) {
Richard Uhler66d874d2015-01-15 09:37:19 -0800616 *error_msg = "Patching of oat file for dex location "
617 + std::string(dex_location_)
Richard Uhler95abd042015-03-24 09:51:28 -0700618 + " not attempted because the input file name could not be determined.";
Richard Uhler66d874d2015-01-15 09:37:19 -0800619 return false;
620 }
Richard Uhler95abd042015-03-24 09:51:28 -0700621 const std::string& input_file_name = *input_file;
Richard Uhler66d874d2015-01-15 09:37:19 -0800622
623 if (OatFileName() == nullptr) {
624 *error_msg = "Patching of oat file for dex location "
625 + std::string(dex_location_)
626 + " not attempted because the oat file name could not be determined.";
627 return false;
628 }
629 const std::string& oat_file_name = *OatFileName();
630
631 const ImageInfo* image_info = GetImageInfo();
632 Runtime* runtime = Runtime::Current();
633 if (image_info == nullptr) {
634 *error_msg = "Patching of oat file " + oat_file_name
635 + " not attempted because no image location was found.";
636 return false;
637 }
638
639 if (!runtime->IsDex2OatEnabled()) {
640 *error_msg = "Patching of oat file " + oat_file_name
641 + " not attempted because dex2oat is disabled";
642 return false;
643 }
644
645 std::vector<std::string> argv;
646 argv.push_back(runtime->GetPatchoatExecutable());
647 argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(isa_)));
Richard Uhler95abd042015-03-24 09:51:28 -0700648 argv.push_back("--input-oat-file=" + input_file_name);
Richard Uhler66d874d2015-01-15 09:37:19 -0800649 argv.push_back("--output-oat-file=" + oat_file_name);
650 argv.push_back("--patched-image-location=" + image_info->location);
651
652 std::string command_line(Join(argv, ' '));
653 if (!Exec(argv, error_msg)) {
654 // Manually delete the file. This ensures there is no garbage left over if
655 // the process unexpectedly died.
656 TEMP_FAILURE_RETRY(unlink(oat_file_name.c_str()));
657 return false;
658 }
659
660 // Mark that the oat file has changed and we should try to reload.
661 ClearOatFileCache();
662 return true;
663}
664
665bool OatFileAssistant::GenerateOatFile(std::string* error_msg) {
666 CHECK(error_msg != nullptr);
667
668 if (OatFileName() == nullptr) {
669 *error_msg = "Generation of oat file for dex location "
670 + std::string(dex_location_)
671 + " not attempted because the oat file name could not be determined.";
672 return false;
673 }
674 const std::string& oat_file_name = *OatFileName();
675
676 Runtime* runtime = Runtime::Current();
677 if (!runtime->IsDex2OatEnabled()) {
678 *error_msg = "Generation of oat file " + oat_file_name
679 + " not attempted because dex2oat is disabled";
680 return false;
681 }
682
683 std::vector<std::string> args;
684 args.push_back("--dex-file=" + std::string(dex_location_));
685 args.push_back("--oat-file=" + oat_file_name);
686
687 // dex2oat ignores missing dex files and doesn't report an error.
688 // Check explicitly here so we can detect the error properly.
689 // TODO: Why does dex2oat behave that way?
690 if (!OS::FileExists(dex_location_)) {
691 *error_msg = "Dex location " + std::string(dex_location_) + " does not exists.";
692 return false;
693 }
694
695 if (!Dex2Oat(args, error_msg)) {
696 // Manually delete the file. This ensures there is no garbage left over if
697 // the process unexpectedly died.
698 TEMP_FAILURE_RETRY(unlink(oat_file_name.c_str()));
699 return false;
700 }
701
702 // Mark that the oat file has changed and we should try to reload.
703 ClearOatFileCache();
704 return true;
705}
706
707bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args,
708 std::string* error_msg) {
709 Runtime* runtime = Runtime::Current();
710 std::string image_location = ImageLocation();
711 if (image_location.empty()) {
712 *error_msg = "No image location found for Dex2Oat.";
713 return false;
714 }
715
716 std::vector<std::string> argv;
717 argv.push_back(runtime->GetCompilerExecutable());
718 argv.push_back("--runtime-arg");
719 argv.push_back("-classpath");
720 argv.push_back("--runtime-arg");
721 argv.push_back(runtime->GetClassPathString());
Nicolas Geoffray7a4d0152015-07-10 17:29:39 +0100722 if (runtime->IsDebuggable()) {
Sebastien Hertz0de11332015-05-13 12:14:05 +0200723 argv.push_back("--debuggable");
724 }
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700725 runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
Richard Uhler66d874d2015-01-15 09:37:19 -0800726
727 if (!runtime->IsVerificationEnabled()) {
728 argv.push_back("--compiler-filter=verify-none");
729 }
730
731 if (runtime->MustRelocateIfPossible()) {
732 argv.push_back("--runtime-arg");
733 argv.push_back("-Xrelocate");
734 } else {
735 argv.push_back("--runtime-arg");
736 argv.push_back("-Xnorelocate");
737 }
738
739 if (!kIsTargetBuild) {
740 argv.push_back("--host");
741 }
742
743 argv.push_back("--boot-image=" + image_location);
744
745 std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
746 argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
747
748 argv.insert(argv.end(), args.begin(), args.end());
749
750 std::string command_line(Join(argv, ' '));
751 return Exec(argv, error_msg);
752}
753
754bool OatFileAssistant::DexFilenameToOdexFilename(const std::string& location,
755 InstructionSet isa, std::string* odex_filename, std::string* error_msg) {
756 CHECK(odex_filename != nullptr);
757 CHECK(error_msg != nullptr);
758
759 // The odex file name is formed by replacing the dex_location extension with
Richard Uhler63434112015-03-16 14:32:16 -0700760 // .odex and inserting an oat/<isa> directory. For example:
Richard Uhler66d874d2015-01-15 09:37:19 -0800761 // location = /foo/bar/baz.jar
Richard Uhler63434112015-03-16 14:32:16 -0700762 // odex_location = /foo/bar/oat/<isa>/baz.odex
Richard Uhler66d874d2015-01-15 09:37:19 -0800763
Richard Uhler63434112015-03-16 14:32:16 -0700764 // Find the directory portion of the dex location and add the oat/<isa>
765 // directory.
Richard Uhler66d874d2015-01-15 09:37:19 -0800766 size_t pos = location.rfind('/');
767 if (pos == std::string::npos) {
768 *error_msg = "Dex location " + location + " has no directory.";
769 return false;
770 }
771 std::string dir = location.substr(0, pos+1);
Richard Uhler63434112015-03-16 14:32:16 -0700772 dir += "oat/" + std::string(GetInstructionSetString(isa));
Richard Uhler66d874d2015-01-15 09:37:19 -0800773
774 // Find the file portion of the dex location.
775 std::string file;
776 if (pos == std::string::npos) {
777 file = location;
778 } else {
779 file = location.substr(pos+1);
780 }
781
782 // Get the base part of the file without the extension.
783 pos = file.rfind('.');
784 if (pos == std::string::npos) {
785 *error_msg = "Dex location " + location + " has no extension.";
786 return false;
787 }
788 std::string base = file.substr(0, pos);
789
790 *odex_filename = dir + "/" + base + ".odex";
791 return true;
792}
793
794std::string OatFileAssistant::DalvikCacheDirectory() {
795 // Note: We don't cache this, because it will only be called once by
796 // OatFileName, and we don't care about the performance of the profiling
797 // code, which isn't used in practice.
798
799 // TODO: The work done in GetDalvikCache is overkill for what we need.
800 // Ideally a new API for getting the DalvikCacheDirectory the way we want
801 // (without existence testing, creation, or death) is provided with the rest
802 // of the GetDalvikCache family of functions. Until such an API is in place,
803 // we use GetDalvikCache to avoid duplicating the logic for determining the
804 // dalvik cache directory.
805 std::string result;
806 bool have_android_data;
807 bool dalvik_cache_exists;
808 bool is_global_cache;
809 GetDalvikCache("", false, &result, &have_android_data, &dalvik_cache_exists, &is_global_cache);
810 return result;
811}
812
813std::string OatFileAssistant::ProfileFileName() {
814 if (package_name_ != nullptr) {
815 return DalvikCacheDirectory() + std::string("profiles/") + package_name_;
816 }
817 return "";
818}
819
820std::string OatFileAssistant::OldProfileFileName() {
821 std::string profile_name = ProfileFileName();
822 if (profile_name.empty()) {
823 return "";
824 }
825 return profile_name + "@old";
826}
827
828std::string OatFileAssistant::ImageLocation() {
829 Runtime* runtime = Runtime::Current();
830 const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace();
831 if (image_space == nullptr) {
832 return "";
833 }
834 return image_space->GetImageLocation();
835}
836
837const uint32_t* OatFileAssistant::GetRequiredDexChecksum() {
Richard Uhler9b994ea2015-06-24 08:44:19 -0700838 if (!required_dex_checksum_attempted_) {
839 required_dex_checksum_attempted_ = true;
840 required_dex_checksum_found_ = false;
Richard Uhler66d874d2015-01-15 09:37:19 -0800841 std::string error_msg;
842 CHECK(dex_location_ != nullptr) << "OatFileAssistant provided no dex location";
Richard Uhler9b994ea2015-06-24 08:44:19 -0700843 if (DexFile::GetChecksum(dex_location_, &cached_required_dex_checksum_, &error_msg)) {
844 required_dex_checksum_found_ = true;
845 has_original_dex_files_ = true;
Richard Uhler66d874d2015-01-15 09:37:19 -0800846 } else {
847 // This can happen if the original dex file has been stripped from the
848 // apk.
849 VLOG(oat) << "OatFileAssistant: " << error_msg;
Richard Uhler9b994ea2015-06-24 08:44:19 -0700850 has_original_dex_files_ = false;
Richard Uhler66d874d2015-01-15 09:37:19 -0800851
852 // Get the checksum from the odex if we can.
853 const OatFile* odex_file = GetOdexFile();
854 if (odex_file != nullptr) {
855 const OatFile::OatDexFile* odex_dex_file = odex_file->GetOatDexFile(
856 dex_location_, nullptr, false);
857 if (odex_dex_file != nullptr) {
Richard Uhler9b994ea2015-06-24 08:44:19 -0700858 cached_required_dex_checksum_ = odex_dex_file->GetDexFileLocationChecksum();
859 required_dex_checksum_found_ = true;
Richard Uhler66d874d2015-01-15 09:37:19 -0800860 }
861 }
862 }
863 }
Richard Uhler9b994ea2015-06-24 08:44:19 -0700864 return required_dex_checksum_found_ ? &cached_required_dex_checksum_ : nullptr;
Richard Uhler66d874d2015-01-15 09:37:19 -0800865}
866
867const OatFile* OatFileAssistant::GetOdexFile() {
868 CHECK(!oat_file_released_) << "OdexFile called after oat file released.";
869 if (!odex_file_load_attempted_) {
870 odex_file_load_attempted_ = true;
871 if (OdexFileName() != nullptr) {
872 const std::string& odex_file_name = *OdexFileName();
873 std::string error_msg;
874 cached_odex_file_.reset(OatFile::Open(odex_file_name.c_str(),
875 odex_file_name.c_str(), nullptr, nullptr, load_executable_,
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700876 dex_location_, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -0800877 if (cached_odex_file_.get() == nullptr) {
878 VLOG(oat) << "OatFileAssistant test for existing pre-compiled oat file "
879 << odex_file_name << ": " << error_msg;
880 }
881 }
882 }
883 return cached_odex_file_.get();
884}
885
Richard Uhler5f946da2015-07-17 12:28:32 -0700886bool OatFileAssistant::OdexFileIsExecutable() {
887 const OatFile* odex_file = GetOdexFile();
888 return (odex_file != nullptr && odex_file->IsExecutable());
889}
890
Richard Uhler66d874d2015-01-15 09:37:19 -0800891void OatFileAssistant::ClearOdexFileCache() {
892 odex_file_load_attempted_ = false;
893 cached_odex_file_.reset();
894 odex_file_is_out_of_date_attempted_ = false;
895 odex_file_is_up_to_date_attempted_ = false;
896}
897
898const OatFile* OatFileAssistant::GetOatFile() {
899 CHECK(!oat_file_released_) << "OatFile called after oat file released.";
900 if (!oat_file_load_attempted_) {
901 oat_file_load_attempted_ = true;
902 if (OatFileName() != nullptr) {
903 const std::string& oat_file_name = *OatFileName();
904 std::string error_msg;
905 cached_oat_file_.reset(OatFile::Open(oat_file_name.c_str(),
Richard Uhlere5fed032015-03-18 08:21:11 -0700906 oat_file_name.c_str(), nullptr, nullptr, load_executable_,
Igor Murashkinb1d8c312015-08-04 11:18:43 -0700907 dex_location_, &error_msg));
Richard Uhler66d874d2015-01-15 09:37:19 -0800908 if (cached_oat_file_.get() == nullptr) {
909 VLOG(oat) << "OatFileAssistant test for existing oat file "
910 << oat_file_name << ": " << error_msg;
911 }
912 }
913 }
914 return cached_oat_file_.get();
915}
916
Richard Uhler5f946da2015-07-17 12:28:32 -0700917bool OatFileAssistant::OatFileIsExecutable() {
918 const OatFile* oat_file = GetOatFile();
919 return (oat_file != nullptr && oat_file->IsExecutable());
920}
921
Richard Uhler66d874d2015-01-15 09:37:19 -0800922void OatFileAssistant::ClearOatFileCache() {
923 oat_file_load_attempted_ = false;
924 cached_oat_file_.reset();
925 oat_file_is_out_of_date_attempted_ = false;
926 oat_file_is_up_to_date_attempted_ = false;
927}
928
929const OatFileAssistant::ImageInfo* OatFileAssistant::GetImageInfo() {
930 if (!image_info_load_attempted_) {
931 image_info_load_attempted_ = true;
932
933 Runtime* runtime = Runtime::Current();
934 const gc::space::ImageSpace* image_space = runtime->GetHeap()->GetImageSpace();
935 if (image_space != nullptr) {
936 cached_image_info_.location = image_space->GetImageLocation();
937
938 if (isa_ == kRuntimeISA) {
939 const ImageHeader& image_header = image_space->GetImageHeader();
940 cached_image_info_.oat_checksum = image_header.GetOatChecksum();
941 cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin());
942 cached_image_info_.patch_delta = image_header.GetPatchDelta();
943 } else {
944 std::unique_ptr<ImageHeader> image_header(
945 gc::space::ImageSpace::ReadImageHeaderOrDie(
946 cached_image_info_.location.c_str(), isa_));
947 cached_image_info_.oat_checksum = image_header->GetOatChecksum();
948 cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin());
949 cached_image_info_.patch_delta = image_header->GetPatchDelta();
950 }
951 }
952 image_info_load_succeeded_ = (image_space != nullptr);
953 }
954 return image_info_load_succeeded_ ? &cached_image_info_ : nullptr;
955}
956
957ProfileFile* OatFileAssistant::GetProfile() {
958 if (!profile_load_attempted_) {
959 CHECK(package_name_ != nullptr)
960 << "pakage_name_ is nullptr: "
961 << "profile_load_attempted_ should have been true";
962 profile_load_attempted_ = true;
963 std::string profile_name = ProfileFileName();
964 if (!profile_name.empty()) {
965 profile_load_succeeded_ = cached_profile_.LoadFile(profile_name);
966 }
967 }
968 return profile_load_succeeded_ ? &cached_profile_ : nullptr;
969}
970
971ProfileFile* OatFileAssistant::GetOldProfile() {
972 if (!old_profile_load_attempted_) {
973 CHECK(package_name_ != nullptr)
974 << "pakage_name_ is nullptr: "
975 << "old_profile_load_attempted_ should have been true";
976 old_profile_load_attempted_ = true;
977 std::string old_profile_name = OldProfileFileName();
978 if (!old_profile_name.empty()) {
979 old_profile_load_succeeded_ = cached_old_profile_.LoadFile(old_profile_name);
980 }
981 }
982 return old_profile_load_succeeded_ ? &cached_old_profile_ : nullptr;
983}
984
985} // namespace art
986