1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#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 "compiler_filter.h"
34#include "class_linker.h"
35#include "gc/heap.h"
36#include "gc/space/image_space.h"
37#include "image.h"
38#include "oat.h"
39#include "os.h"
40#include "runtime.h"
41#include "scoped_thread_state_change.h"
42#include "ScopedFd.h"
43#include "utils.h"
44
45namespace art {
46
47std::ostream& operator << (std::ostream& stream, const OatFileAssistant::OatStatus status) {
48  switch (status) {
49    case OatFileAssistant::kOatOutOfDate:
50      stream << "kOatOutOfDate";
51      break;
52    case OatFileAssistant::kOatUpToDate:
53      stream << "kOatUpToDate";
54      break;
55    case OatFileAssistant::kOatNeedsRelocation:
56      stream << "kOatNeedsRelocation";
57      break;
58    default:
59      UNREACHABLE();
60  }
61
62  return stream;
63}
64
65OatFileAssistant::OatFileAssistant(const char* dex_location,
66                                   const InstructionSet isa,
67                                   bool profile_changed,
68                                   bool load_executable)
69    : OatFileAssistant(dex_location, nullptr, isa, profile_changed, load_executable)
70{ }
71
72OatFileAssistant::OatFileAssistant(const char* dex_location,
73                                   const char* oat_location,
74                                   const InstructionSet isa,
75                                   bool profile_changed,
76                                   bool load_executable)
77    : isa_(isa), profile_changed_(profile_changed), load_executable_(load_executable) {
78  CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location";
79  dex_location_.assign(dex_location);
80
81  if (load_executable_ && isa != kRuntimeISA) {
82    LOG(WARNING) << "OatFileAssistant: Load executable specified, "
83      << "but isa is not kRuntimeISA. Will not attempt to load executable.";
84    load_executable_ = false;
85  }
86
87  // If the user gave a target oat location, save that as the cached oat
88  // location now so we won't try to construct the default location later.
89  if (oat_location != nullptr) {
90    cached_oat_file_name_ = std::string(oat_location);
91    cached_oat_file_name_attempted_ = true;
92    cached_oat_file_name_found_ = true;
93  }
94}
95
96OatFileAssistant::~OatFileAssistant() {
97  // Clean up the lock file.
98  if (flock_.HasFile()) {
99    unlink(flock_.GetFile()->GetPath().c_str());
100  }
101}
102
103bool OatFileAssistant::IsInBootClassPath() {
104  // Note: We check the current boot class path, regardless of the ISA
105  // specified by the user. This is okay, because the boot class path should
106  // be the same for all ISAs.
107  // TODO: Can we verify the boot class path is the same for all ISAs?
108  Runtime* runtime = Runtime::Current();
109  ClassLinker* class_linker = runtime->GetClassLinker();
110  const auto& boot_class_path = class_linker->GetBootClassPath();
111  for (size_t i = 0; i < boot_class_path.size(); i++) {
112    if (boot_class_path[i]->GetLocation() == dex_location_) {
113      VLOG(oat) << "Dex location " << dex_location_ << " is in boot class path";
114      return true;
115    }
116  }
117  return false;
118}
119
120bool OatFileAssistant::Lock(std::string* error_msg) {
121  CHECK(error_msg != nullptr);
122  CHECK(!flock_.HasFile()) << "OatFileAssistant::Lock already acquired";
123
124  if (OatFileName() == nullptr) {
125    *error_msg = "Failed to determine lock file";
126    return false;
127  }
128  std::string lock_file_name = *OatFileName() + ".flock";
129
130  if (!flock_.Init(lock_file_name.c_str(), error_msg)) {
131    unlink(lock_file_name.c_str());
132    return false;
133  }
134  return true;
135}
136
137bool OatFileAssistant::OatFileCompilerFilterIsOkay(CompilerFilter::Filter target) {
138  const OatFile* oat_file = GetOatFile();
139  if (oat_file != nullptr) {
140    CompilerFilter::Filter current = oat_file->GetCompilerFilter();
141    return CompilerFilter::IsAsGoodAs(current, target);
142  }
143  return false;
144}
145
146bool OatFileAssistant::OdexFileCompilerFilterIsOkay(CompilerFilter::Filter target) {
147  const OatFile* odex_file = GetOdexFile();
148  if (odex_file != nullptr) {
149    CompilerFilter::Filter current = odex_file->GetCompilerFilter();
150    return CompilerFilter::IsAsGoodAs(current, target);
151  }
152  return false;
153}
154
155OatFileAssistant::DexOptNeeded OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target) {
156  bool compilation_desired = CompilerFilter::IsBytecodeCompilationEnabled(target);
157
158  // See if the oat file is in good shape as is.
159  bool oat_okay = OatFileCompilerFilterIsOkay(target);
160  if (oat_okay) {
161    if (compilation_desired) {
162      if (OatFileIsUpToDate()) {
163        return kNoDexOptNeeded;
164      }
165    } else {
166      if (!OatFileIsOutOfDate()) {
167        return kNoDexOptNeeded;
168      }
169    }
170  }
171
172  // See if the odex file is in good shape as is.
173  bool odex_okay = OdexFileCompilerFilterIsOkay(target);
174  if (odex_okay) {
175    if (compilation_desired) {
176      if (OdexFileIsUpToDate()) {
177        return kNoDexOptNeeded;
178      }
179    } else {
180      if (!OdexFileIsOutOfDate()) {
181        return kNoDexOptNeeded;
182      }
183    }
184  }
185
186  // See if we can get an up-to-date file by running patchoat.
187  if (compilation_desired) {
188    if (odex_okay && OdexFileNeedsRelocation() && OdexFileHasPatchInfo()) {
189      return kPatchOatNeeded;
190    }
191
192    if (oat_okay && OatFileNeedsRelocation() && OatFileHasPatchInfo()) {
193      return kSelfPatchOatNeeded;
194    }
195  }
196
197  // We can only run dex2oat if there are original dex files.
198  return HasOriginalDexFiles() ? kDex2OatNeeded : kNoDexOptNeeded;
199}
200
201bool OatFileAssistant::IsUpToDate() {
202  return OatFileIsUpToDate() || OdexFileIsUpToDate();
203}
204
205OatFileAssistant::ResultOfAttemptToUpdate
206OatFileAssistant::MakeUpToDate(CompilerFilter::Filter target, std::string* error_msg) {
207  switch (GetDexOptNeeded(target)) {
208    case kNoDexOptNeeded: return kUpdateSucceeded;
209    case kDex2OatNeeded: return GenerateOatFile(target, error_msg);
210    case kPatchOatNeeded: return RelocateOatFile(OdexFileName(), error_msg);
211    case kSelfPatchOatNeeded: return RelocateOatFile(OatFileName(), error_msg);
212  }
213  UNREACHABLE();
214}
215
216std::unique_ptr<OatFile> OatFileAssistant::GetBestOatFile() {
217  // The best oat files are, in descending order of bestness:
218  // 1. Properly relocated files. These may be opened executable.
219  // 2. Not out-of-date files that are already opened non-executable.
220  // 3. Not out-of-date files that we must reopen non-executable.
221
222  if (OatFileIsUpToDate()) {
223    oat_file_released_ = true;
224    return std::move(cached_oat_file_);
225  }
226
227  if (OdexFileIsUpToDate()) {
228    oat_file_released_ = true;
229    return std::move(cached_odex_file_);
230  }
231
232  VLOG(oat) << "Oat File Assistant: No relocated oat file found,"
233    << " attempting to fall back to interpreting oat file instead.";
234
235  if (!OatFileIsOutOfDate() && !OatFileIsExecutable()) {
236    oat_file_released_ = true;
237    return std::move(cached_oat_file_);
238  }
239
240  if (!OdexFileIsOutOfDate() && !OdexFileIsExecutable()) {
241    oat_file_released_ = true;
242    return std::move(cached_odex_file_);
243  }
244
245  if (!OatFileIsOutOfDate()) {
246    load_executable_ = false;
247    ClearOatFileCache();
248    if (!OatFileIsOutOfDate()) {
249      CHECK(!OatFileIsExecutable());
250      oat_file_released_ = true;
251      return std::move(cached_oat_file_);
252    }
253  }
254
255  if (!OdexFileIsOutOfDate()) {
256    load_executable_ = false;
257    ClearOdexFileCache();
258    if (!OdexFileIsOutOfDate()) {
259      CHECK(!OdexFileIsExecutable());
260      oat_file_released_ = true;
261      return std::move(cached_odex_file_);
262    }
263  }
264
265  return std::unique_ptr<OatFile>();
266}
267
268std::vector<std::unique_ptr<const DexFile>> OatFileAssistant::LoadDexFiles(
269    const OatFile& oat_file, const char* dex_location) {
270  std::vector<std::unique_ptr<const DexFile>> dex_files;
271
272  // Load the primary dex file.
273  std::string error_msg;
274  const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(
275      dex_location, nullptr, false);
276  if (oat_dex_file == nullptr) {
277    LOG(WARNING) << "Attempt to load out-of-date oat file "
278      << oat_file.GetLocation() << " for dex location " << dex_location;
279    return std::vector<std::unique_ptr<const DexFile>>();
280  }
281
282  std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
283  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  // Load secondary multidex files
290  for (size_t i = 1; ; i++) {
291    std::string secondary_dex_location = DexFile::GetMultiDexLocation(i, dex_location);
292    oat_dex_file = oat_file.GetOatDexFile(secondary_dex_location.c_str(), nullptr, false);
293    if (oat_dex_file == nullptr) {
294      // There are no more secondary dex files to load.
295      break;
296    }
297
298    dex_file = oat_dex_file->OpenDexFile(&error_msg);
299    if (dex_file.get() == nullptr) {
300      LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
301      return std::vector<std::unique_ptr<const DexFile>>();
302    }
303    dex_files.push_back(std::move(dex_file));
304  }
305  return dex_files;
306}
307
308bool OatFileAssistant::HasOriginalDexFiles() {
309  // Ensure GetRequiredDexChecksum has been run so that
310  // has_original_dex_files_ is initialized. We don't care about the result of
311  // GetRequiredDexChecksum.
312  GetRequiredDexChecksum();
313  return has_original_dex_files_;
314}
315
316const std::string* OatFileAssistant::OdexFileName() {
317  if (!cached_odex_file_name_attempted_) {
318    cached_odex_file_name_attempted_ = true;
319
320    std::string error_msg;
321    cached_odex_file_name_found_ = DexFilenameToOdexFilename(
322        dex_location_, isa_, &cached_odex_file_name_, &error_msg);
323    if (!cached_odex_file_name_found_) {
324      // If we can't figure out the odex file, we treat it as if the odex
325      // file was inaccessible.
326      LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
327    }
328  }
329  return cached_odex_file_name_found_ ? &cached_odex_file_name_ : nullptr;
330}
331
332bool OatFileAssistant::OdexFileExists() {
333  return GetOdexFile() != nullptr;
334}
335
336OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() {
337  if (OdexFileIsOutOfDate()) {
338    return kOatOutOfDate;
339  }
340  if (OdexFileIsUpToDate()) {
341    return kOatUpToDate;
342  }
343  return kOatNeedsRelocation;
344}
345
346bool OatFileAssistant::OdexFileIsOutOfDate() {
347  if (!odex_file_is_out_of_date_attempted_) {
348    odex_file_is_out_of_date_attempted_ = true;
349    const OatFile* odex_file = GetOdexFile();
350    if (odex_file == nullptr) {
351      cached_odex_file_is_out_of_date_ = true;
352    } else {
353      cached_odex_file_is_out_of_date_ = GivenOatFileIsOutOfDate(*odex_file);
354    }
355  }
356  return cached_odex_file_is_out_of_date_;
357}
358
359bool OatFileAssistant::OdexFileNeedsRelocation() {
360  return OdexFileStatus() == kOatNeedsRelocation;
361}
362
363bool OatFileAssistant::OdexFileIsUpToDate() {
364  if (!odex_file_is_up_to_date_attempted_) {
365    odex_file_is_up_to_date_attempted_ = true;
366    const OatFile* odex_file = GetOdexFile();
367    if (odex_file == nullptr) {
368      cached_odex_file_is_up_to_date_ = false;
369    } else {
370      cached_odex_file_is_up_to_date_ = GivenOatFileIsUpToDate(*odex_file);
371    }
372  }
373  return cached_odex_file_is_up_to_date_;
374}
375
376CompilerFilter::Filter OatFileAssistant::OdexFileCompilerFilter() {
377  const OatFile* odex_file = GetOdexFile();
378  CHECK(odex_file != nullptr);
379
380  return odex_file->GetCompilerFilter();
381}
382std::string OatFileAssistant::ArtFileName(const OatFile* oat_file) const {
383  const std::string oat_file_location = oat_file->GetLocation();
384  // Replace extension with .art
385  const size_t last_ext = oat_file_location.find_last_of('.');
386  if (last_ext == std::string::npos) {
387    LOG(ERROR) << "No extension in oat file " << oat_file_location;
388    return std::string();
389  }
390  return oat_file_location.substr(0, last_ext) + ".art";
391}
392
393const std::string* OatFileAssistant::OatFileName() {
394  if (!cached_oat_file_name_attempted_) {
395    cached_oat_file_name_attempted_ = true;
396
397    // Compute the oat file name from the dex location.
398    // TODO: The oat file assistant should be the definitive place for
399    // determining the oat file name from the dex location, not
400    // GetDalvikCacheFilename.
401    std::string cache_dir = StringPrintf("%s%s",
402        DalvikCacheDirectory().c_str(), GetInstructionSetString(isa_));
403    std::string error_msg;
404    cached_oat_file_name_found_ = GetDalvikCacheFilename(dex_location_.c_str(),
405        cache_dir.c_str(), &cached_oat_file_name_, &error_msg);
406    if (!cached_oat_file_name_found_) {
407      // If we can't determine the oat file name, we treat the oat file as
408      // inaccessible.
409      LOG(WARNING) << "Failed to determine oat file name for dex location "
410        << dex_location_ << ": " << error_msg;
411    }
412  }
413  return cached_oat_file_name_found_ ? &cached_oat_file_name_ : nullptr;
414}
415
416bool OatFileAssistant::OatFileExists() {
417  return GetOatFile() != nullptr;
418}
419
420OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() {
421  if (OatFileIsOutOfDate()) {
422    return kOatOutOfDate;
423  }
424  if (OatFileIsUpToDate()) {
425    return kOatUpToDate;
426  }
427  return kOatNeedsRelocation;
428}
429
430bool OatFileAssistant::OatFileIsOutOfDate() {
431  if (!oat_file_is_out_of_date_attempted_) {
432    oat_file_is_out_of_date_attempted_ = true;
433    const OatFile* oat_file = GetOatFile();
434    if (oat_file == nullptr) {
435      cached_oat_file_is_out_of_date_ = true;
436    } else {
437      cached_oat_file_is_out_of_date_ = GivenOatFileIsOutOfDate(*oat_file);
438    }
439  }
440  return cached_oat_file_is_out_of_date_;
441}
442
443bool OatFileAssistant::OatFileNeedsRelocation() {
444  return OatFileStatus() == kOatNeedsRelocation;
445}
446
447bool OatFileAssistant::OatFileIsUpToDate() {
448  if (!oat_file_is_up_to_date_attempted_) {
449    oat_file_is_up_to_date_attempted_ = true;
450    const OatFile* oat_file = GetOatFile();
451    if (oat_file == nullptr) {
452      cached_oat_file_is_up_to_date_ = false;
453    } else {
454      cached_oat_file_is_up_to_date_ = GivenOatFileIsUpToDate(*oat_file);
455    }
456  }
457  return cached_oat_file_is_up_to_date_;
458}
459
460CompilerFilter::Filter OatFileAssistant::OatFileCompilerFilter() {
461  const OatFile* oat_file = GetOatFile();
462  CHECK(oat_file != nullptr);
463
464  return oat_file->GetCompilerFilter();
465}
466
467OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
468  // TODO: This could cause GivenOatFileIsOutOfDate to be called twice, which
469  // is more work than we need to do. If performance becomes a concern, and
470  // this method is actually called, this should be fixed.
471  if (GivenOatFileIsOutOfDate(file)) {
472    return kOatOutOfDate;
473  }
474  if (GivenOatFileIsUpToDate(file)) {
475    return kOatUpToDate;
476  }
477  return kOatNeedsRelocation;
478}
479
480bool OatFileAssistant::GivenOatFileIsOutOfDate(const OatFile& file) {
481  // Verify the dex checksum.
482  // Note: GetOatDexFile will return null if the dex checksum doesn't match
483  // what we provide, which verifies the primary dex checksum for us.
484  const uint32_t* dex_checksum_pointer = GetRequiredDexChecksum();
485  const OatFile::OatDexFile* oat_dex_file = file.GetOatDexFile(
486      dex_location_.c_str(), dex_checksum_pointer, false);
487  if (oat_dex_file == nullptr) {
488    return true;
489  }
490
491  // Verify the dex checksums for any secondary multidex files
492  for (size_t i = 1; ; i++) {
493    std::string secondary_dex_location
494      = DexFile::GetMultiDexLocation(i, dex_location_.c_str());
495    const OatFile::OatDexFile* secondary_oat_dex_file
496      = file.GetOatDexFile(secondary_dex_location.c_str(), nullptr, false);
497    if (secondary_oat_dex_file == nullptr) {
498      // There are no more secondary dex files to check.
499      break;
500    }
501
502    std::string error_msg;
503    uint32_t expected_secondary_checksum = 0;
504    if (DexFile::GetChecksum(secondary_dex_location.c_str(),
505          &expected_secondary_checksum, &error_msg)) {
506      uint32_t actual_secondary_checksum
507        = secondary_oat_dex_file->GetDexFileLocationChecksum();
508      if (expected_secondary_checksum != actual_secondary_checksum) {
509        VLOG(oat) << "Dex checksum does not match for secondary dex: "
510          << secondary_dex_location
511          << ". Expected: " << expected_secondary_checksum
512          << ", Actual: " << actual_secondary_checksum;
513        return true;
514      }
515    } else {
516      // If we can't get the checksum for the secondary location, we assume
517      // the dex checksum is up to date for this and all other secondary dex
518      // files.
519      break;
520    }
521  }
522
523  CompilerFilter::Filter current_compiler_filter = file.GetCompilerFilter();
524  VLOG(oat) << "Compiler filter for " << file.GetLocation() << " is " << current_compiler_filter;
525
526  // Verify the image checksum
527  if (CompilerFilter::DependsOnImageChecksum(current_compiler_filter)) {
528    const ImageInfo* image_info = GetImageInfo();
529    if (image_info == nullptr) {
530      VLOG(oat) << "No image for oat image checksum to match against.";
531
532      if (HasOriginalDexFiles()) {
533        return true;
534      }
535
536      // If there is no original dex file to fall back to, grudgingly accept
537      // the oat file. This could technically lead to crashes, but there's no
538      // way we could find a better oat file to use for this dex location,
539      // and it's better than being stuck in a boot loop with no way out.
540      // The problem will hopefully resolve itself the next time the runtime
541      // starts up.
542      LOG(WARNING) << "Dex location " << dex_location_ << " does not seem to include dex file. "
543        << "Allow oat file use. This is potentially dangerous.";
544    } else if (file.GetOatHeader().GetImageFileLocationOatChecksum()
545        != GetCombinedImageChecksum()) {
546      VLOG(oat) << "Oat image checksum does not match image checksum.";
547      return true;
548    }
549  } else {
550    VLOG(oat) << "Image checksum test skipped for compiler filter " << current_compiler_filter;
551  }
552
553  // Verify the profile hasn't changed recently.
554  // TODO: Move this check to OatFileCompilerFilterIsOkay? Nothing bad should
555  // happen if we use an oat file compiled with an out-of-date profile.
556  if (CompilerFilter::DependsOnProfile(current_compiler_filter)) {
557    if (profile_changed_) {
558      VLOG(oat) << "The profile has changed recently.";
559      return true;
560    }
561  } else {
562    VLOG(oat) << "Profile check skipped for compiler filter " << current_compiler_filter;
563  }
564
565  // Everything looks good; the dex file is not out of date.
566  return false;
567}
568
569bool OatFileAssistant::GivenOatFileNeedsRelocation(const OatFile& file) {
570  return GivenOatFileStatus(file) == kOatNeedsRelocation;
571}
572
573bool OatFileAssistant::GivenOatFileIsUpToDate(const OatFile& file) {
574  if (GivenOatFileIsOutOfDate(file)) {
575    return false;
576  }
577
578  CompilerFilter::Filter current_compiler_filter = file.GetCompilerFilter();
579
580  if (CompilerFilter::IsBytecodeCompilationEnabled(current_compiler_filter)) {
581    if (!file.IsPic()) {
582      const ImageInfo* image_info = GetImageInfo();
583      if (image_info == nullptr) {
584        VLOG(oat) << "No image to check oat relocation against.";
585        return false;
586      }
587
588      // Verify the oat_data_begin recorded for the image in the oat file matches
589      // the actual oat_data_begin for boot.oat in the image.
590      const OatHeader& oat_header = file.GetOatHeader();
591      uintptr_t oat_data_begin = oat_header.GetImageFileLocationOatDataBegin();
592      if (oat_data_begin != image_info->oat_data_begin) {
593        VLOG(oat) << file.GetLocation() <<
594          ": Oat file image oat_data_begin (" << oat_data_begin << ")"
595          << " does not match actual image oat_data_begin ("
596          << image_info->oat_data_begin << ")";
597        return false;
598      }
599
600      // Verify the oat_patch_delta recorded for the image in the oat file matches
601      // the actual oat_patch_delta for the image.
602      int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
603      if (oat_patch_delta != image_info->patch_delta) {
604        VLOG(oat) << file.GetLocation() <<
605          ": Oat file image patch delta (" << oat_patch_delta << ")"
606          << " does not match actual image patch delta ("
607          << image_info->patch_delta << ")";
608        return false;
609      }
610    } else {
611      // Oat files compiled in PIC mode do not require relocation.
612      VLOG(oat) << "Oat relocation test skipped for PIC oat file";
613    }
614  } else {
615    VLOG(oat) << "Oat relocation test skipped for compiler filter " << current_compiler_filter;
616  }
617  return true;
618}
619
620OatFileAssistant::ResultOfAttemptToUpdate
621OatFileAssistant::RelocateOatFile(const std::string* input_file, std::string* error_msg) {
622  CHECK(error_msg != nullptr);
623
624  if (input_file == nullptr) {
625    *error_msg = "Patching of oat file for dex location " + dex_location_
626      + " not attempted because the input file name could not be determined.";
627    return kUpdateNotAttempted;
628  }
629  const std::string& input_file_name = *input_file;
630
631  if (OatFileName() == nullptr) {
632    *error_msg = "Patching of oat file for dex location " + dex_location_
633      + " not attempted because the oat file name could not be determined.";
634    return kUpdateNotAttempted;
635  }
636  const std::string& oat_file_name = *OatFileName();
637
638  const ImageInfo* image_info = GetImageInfo();
639  Runtime* runtime = Runtime::Current();
640  if (image_info == nullptr) {
641    *error_msg = "Patching of oat file " + oat_file_name
642      + " not attempted because no image location was found.";
643    return kUpdateNotAttempted;
644  }
645
646  if (!runtime->IsDex2OatEnabled()) {
647    *error_msg = "Patching of oat file " + oat_file_name
648      + " not attempted because dex2oat is disabled";
649    return kUpdateNotAttempted;
650  }
651
652  std::vector<std::string> argv;
653  argv.push_back(runtime->GetPatchoatExecutable());
654  argv.push_back("--instruction-set=" + std::string(GetInstructionSetString(isa_)));
655  argv.push_back("--input-oat-file=" + input_file_name);
656  argv.push_back("--output-oat-file=" + oat_file_name);
657  argv.push_back("--patched-image-location=" + image_info->location);
658
659  std::string command_line(Join(argv, ' '));
660  if (!Exec(argv, error_msg)) {
661    // Manually delete the file. This ensures there is no garbage left over if
662    // the process unexpectedly died.
663    unlink(oat_file_name.c_str());
664    return kUpdateFailed;
665  }
666
667  // Mark that the oat file has changed and we should try to reload.
668  ClearOatFileCache();
669  return kUpdateSucceeded;
670}
671
672OatFileAssistant::ResultOfAttemptToUpdate
673OatFileAssistant::GenerateOatFile(CompilerFilter::Filter target, std::string* error_msg) {
674  CHECK(error_msg != nullptr);
675
676  Runtime* runtime = Runtime::Current();
677  if (!runtime->IsDex2OatEnabled()) {
678    *error_msg = "Generation of oat file for dex location " + dex_location_
679      + " not attempted because dex2oat is disabled.";
680    return kUpdateNotAttempted;
681  }
682
683  if (OatFileName() == nullptr) {
684    *error_msg = "Generation of oat file for dex location " + dex_location_
685      + " not attempted because the oat file name could not be determined.";
686    return kUpdateNotAttempted;
687  }
688  const std::string& oat_file_name = *OatFileName();
689
690  // dex2oat ignores missing dex files and doesn't report an error.
691  // Check explicitly here so we can detect the error properly.
692  // TODO: Why does dex2oat behave that way?
693  if (!OS::FileExists(dex_location_.c_str())) {
694    *error_msg = "Dex location " + dex_location_ + " does not exists.";
695    return kUpdateNotAttempted;
696  }
697
698  std::unique_ptr<File> oat_file;
699  oat_file.reset(OS::CreateEmptyFile(oat_file_name.c_str()));
700  if (oat_file.get() == nullptr) {
701    *error_msg = "Generation of oat file " + oat_file_name
702      + " not attempted because the oat file could not be created.";
703    return kUpdateNotAttempted;
704  }
705
706  if (fchmod(oat_file->Fd(), 0644) != 0) {
707    *error_msg = "Generation of oat file " + oat_file_name
708      + " not attempted because the oat file could not be made world readable.";
709    oat_file->Erase();
710    return kUpdateNotAttempted;
711  }
712
713  std::vector<std::string> args;
714  args.push_back("--dex-file=" + dex_location_);
715  args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
716  args.push_back("--oat-location=" + oat_file_name);
717  args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(target));
718
719  if (!Dex2Oat(args, error_msg)) {
720    // Manually delete the file. This ensures there is no garbage left over if
721    // the process unexpectedly died.
722    oat_file->Erase();
723    unlink(oat_file_name.c_str());
724    return kUpdateFailed;
725  }
726
727  if (oat_file->FlushCloseOrErase() != 0) {
728    *error_msg = "Unable to close oat file " + oat_file_name;
729    unlink(oat_file_name.c_str());
730    return kUpdateFailed;
731  }
732
733  // Mark that the oat file has changed and we should try to reload.
734  ClearOatFileCache();
735  return kUpdateSucceeded;
736}
737
738bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args,
739                               std::string* error_msg) {
740  Runtime* runtime = Runtime::Current();
741  std::string image_location = ImageLocation();
742  if (image_location.empty()) {
743    *error_msg = "No image location found for Dex2Oat.";
744    return false;
745  }
746
747  std::vector<std::string> argv;
748  argv.push_back(runtime->GetCompilerExecutable());
749  argv.push_back("--runtime-arg");
750  argv.push_back("-classpath");
751  argv.push_back("--runtime-arg");
752  std::string class_path = runtime->GetClassPathString();
753  if (class_path == "") {
754    class_path = OatFile::kSpecialSharedLibrary;
755  }
756  argv.push_back(class_path);
757  if (runtime->IsDebuggable()) {
758    argv.push_back("--debuggable");
759  }
760  runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
761
762  if (!runtime->IsVerificationEnabled()) {
763    argv.push_back("--compiler-filter=verify-none");
764  }
765
766  if (runtime->MustRelocateIfPossible()) {
767    argv.push_back("--runtime-arg");
768    argv.push_back("-Xrelocate");
769  } else {
770    argv.push_back("--runtime-arg");
771    argv.push_back("-Xnorelocate");
772  }
773
774  if (!kIsTargetBuild) {
775    argv.push_back("--host");
776  }
777
778  argv.push_back("--boot-image=" + image_location);
779
780  std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
781  argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
782
783  argv.insert(argv.end(), args.begin(), args.end());
784
785  std::string command_line(Join(argv, ' '));
786  return Exec(argv, error_msg);
787}
788
789bool OatFileAssistant::DexFilenameToOdexFilename(const std::string& location,
790    InstructionSet isa, std::string* odex_filename, std::string* error_msg) {
791  CHECK(odex_filename != nullptr);
792  CHECK(error_msg != nullptr);
793
794  // The odex file name is formed by replacing the dex_location extension with
795  // .odex and inserting an oat/<isa> directory. For example:
796  //   location = /foo/bar/baz.jar
797  //   odex_location = /foo/bar/oat/<isa>/baz.odex
798
799  // Find the directory portion of the dex location and add the oat/<isa>
800  // directory.
801  size_t pos = location.rfind('/');
802  if (pos == std::string::npos) {
803    *error_msg = "Dex location " + location + " has no directory.";
804    return false;
805  }
806  std::string dir = location.substr(0, pos+1);
807  dir += "oat/" + std::string(GetInstructionSetString(isa));
808
809  // Find the file portion of the dex location.
810  std::string file;
811  if (pos == std::string::npos) {
812    file = location;
813  } else {
814    file = location.substr(pos+1);
815  }
816
817  // Get the base part of the file without the extension.
818  pos = file.rfind('.');
819  if (pos == std::string::npos) {
820    *error_msg = "Dex location " + location + " has no extension.";
821    return false;
822  }
823  std::string base = file.substr(0, pos);
824
825  *odex_filename = dir + "/" + base + ".odex";
826  return true;
827}
828
829std::string OatFileAssistant::DalvikCacheDirectory() {
830  // Note: We don't cache this, because it will only be called once by
831  // OatFileName.
832
833  // TODO: The work done in GetDalvikCache is overkill for what we need.
834  // Ideally a new API for getting the DalvikCacheDirectory the way we want
835  // (without existence testing, creation, or death) is provided with the rest
836  // of the GetDalvikCache family of functions. Until such an API is in place,
837  // we use GetDalvikCache to avoid duplicating the logic for determining the
838  // dalvik cache directory.
839  std::string result;
840  bool have_android_data;
841  bool dalvik_cache_exists;
842  bool is_global_cache;
843  GetDalvikCache("", false, &result, &have_android_data, &dalvik_cache_exists, &is_global_cache);
844  return result;
845}
846
847std::string OatFileAssistant::ImageLocation() {
848  Runtime* runtime = Runtime::Current();
849  const std::vector<gc::space::ImageSpace*>& image_spaces =
850      runtime->GetHeap()->GetBootImageSpaces();
851  if (image_spaces.empty()) {
852    return "";
853  }
854  return image_spaces[0]->GetImageLocation();
855}
856
857const uint32_t* OatFileAssistant::GetRequiredDexChecksum() {
858  if (!required_dex_checksum_attempted_) {
859    required_dex_checksum_attempted_ = true;
860    required_dex_checksum_found_ = false;
861    std::string error_msg;
862    if (DexFile::GetChecksum(dex_location_.c_str(), &cached_required_dex_checksum_, &error_msg)) {
863      required_dex_checksum_found_ = true;
864      has_original_dex_files_ = true;
865    } else {
866      // This can happen if the original dex file has been stripped from the
867      // apk.
868      VLOG(oat) << "OatFileAssistant: " << error_msg;
869      has_original_dex_files_ = false;
870
871      // Get the checksum from the odex if we can.
872      const OatFile* odex_file = GetOdexFile();
873      if (odex_file != nullptr) {
874        const OatFile::OatDexFile* odex_dex_file = odex_file->GetOatDexFile(
875            dex_location_.c_str(), nullptr, false);
876        if (odex_dex_file != nullptr) {
877          cached_required_dex_checksum_ = odex_dex_file->GetDexFileLocationChecksum();
878          required_dex_checksum_found_ = true;
879        }
880      }
881    }
882  }
883  return required_dex_checksum_found_ ? &cached_required_dex_checksum_ : nullptr;
884}
885
886const OatFile* OatFileAssistant::GetOdexFile() {
887  CHECK(!oat_file_released_) << "OdexFile called after oat file released.";
888  if (!odex_file_load_attempted_) {
889    odex_file_load_attempted_ = true;
890    if (OdexFileName() != nullptr) {
891      const std::string& odex_file_name = *OdexFileName();
892      std::string error_msg;
893      cached_odex_file_.reset(OatFile::Open(odex_file_name.c_str(),
894                                            odex_file_name.c_str(),
895                                            nullptr,
896                                            nullptr,
897                                            load_executable_,
898                                            /*low_4gb*/false,
899                                            dex_location_.c_str(),
900                                            &error_msg));
901      if (cached_odex_file_.get() == nullptr) {
902        VLOG(oat) << "OatFileAssistant test for existing pre-compiled oat file "
903          << odex_file_name << ": " << error_msg;
904      }
905    }
906  }
907  return cached_odex_file_.get();
908}
909
910bool OatFileAssistant::OdexFileIsExecutable() {
911  const OatFile* odex_file = GetOdexFile();
912  return (odex_file != nullptr && odex_file->IsExecutable());
913}
914
915bool OatFileAssistant::OdexFileHasPatchInfo() {
916  const OatFile* odex_file = GetOdexFile();
917  return (odex_file != nullptr && odex_file->HasPatchInfo());
918}
919
920void OatFileAssistant::ClearOdexFileCache() {
921  odex_file_load_attempted_ = false;
922  cached_odex_file_.reset();
923  odex_file_is_out_of_date_attempted_ = false;
924  odex_file_is_up_to_date_attempted_ = false;
925}
926
927const OatFile* OatFileAssistant::GetOatFile() {
928  CHECK(!oat_file_released_) << "OatFile called after oat file released.";
929  if (!oat_file_load_attempted_) {
930    oat_file_load_attempted_ = true;
931    if (OatFileName() != nullptr) {
932      const std::string& oat_file_name = *OatFileName();
933      std::string error_msg;
934      cached_oat_file_.reset(OatFile::Open(oat_file_name.c_str(),
935                                           oat_file_name.c_str(),
936                                           nullptr,
937                                           nullptr,
938                                           load_executable_,
939                                           /*low_4gb*/false,
940                                           dex_location_.c_str(),
941                                           &error_msg));
942      if (cached_oat_file_.get() == nullptr) {
943        VLOG(oat) << "OatFileAssistant test for existing oat file "
944          << oat_file_name << ": " << error_msg;
945      }
946    }
947  }
948  return cached_oat_file_.get();
949}
950
951bool OatFileAssistant::OatFileIsExecutable() {
952  const OatFile* oat_file = GetOatFile();
953  return (oat_file != nullptr && oat_file->IsExecutable());
954}
955
956bool OatFileAssistant::OatFileHasPatchInfo() {
957  const OatFile* oat_file = GetOatFile();
958  return (oat_file != nullptr && oat_file->HasPatchInfo());
959}
960
961void OatFileAssistant::ClearOatFileCache() {
962  oat_file_load_attempted_ = false;
963  cached_oat_file_.reset();
964  oat_file_is_out_of_date_attempted_ = false;
965  oat_file_is_up_to_date_attempted_ = false;
966}
967
968const OatFileAssistant::ImageInfo* OatFileAssistant::GetImageInfo() {
969  if (!image_info_load_attempted_) {
970    image_info_load_attempted_ = true;
971
972    Runtime* runtime = Runtime::Current();
973    std::vector<gc::space::ImageSpace*> image_spaces = runtime->GetHeap()->GetBootImageSpaces();
974    if (!image_spaces.empty()) {
975      cached_image_info_.location = image_spaces[0]->GetImageLocation();
976
977      if (isa_ == kRuntimeISA) {
978        const ImageHeader& image_header = image_spaces[0]->GetImageHeader();
979        cached_image_info_.oat_checksum = image_header.GetOatChecksum();
980        cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(
981            image_header.GetOatDataBegin());
982        cached_image_info_.patch_delta = image_header.GetPatchDelta();
983      } else {
984        std::unique_ptr<ImageHeader> image_header(
985            gc::space::ImageSpace::ReadImageHeaderOrDie(cached_image_info_.location.c_str(), isa_));
986        cached_image_info_.oat_checksum = image_header->GetOatChecksum();
987        cached_image_info_.oat_data_begin = reinterpret_cast<uintptr_t>(
988            image_header->GetOatDataBegin());
989        cached_image_info_.patch_delta = image_header->GetPatchDelta();
990      }
991    }
992    image_info_load_succeeded_ = (!image_spaces.empty());
993
994    combined_image_checksum_ = CalculateCombinedImageChecksum(isa_);
995  }
996  return image_info_load_succeeded_ ? &cached_image_info_ : nullptr;
997}
998
999// TODO: Use something better than xor.
1000uint32_t OatFileAssistant::CalculateCombinedImageChecksum(InstructionSet isa) {
1001  uint32_t checksum = 0;
1002  std::vector<gc::space::ImageSpace*> image_spaces =
1003      Runtime::Current()->GetHeap()->GetBootImageSpaces();
1004  if (isa == kRuntimeISA) {
1005    for (gc::space::ImageSpace* image_space : image_spaces) {
1006      checksum ^= image_space->GetImageHeader().GetOatChecksum();
1007    }
1008  } else {
1009    for (gc::space::ImageSpace* image_space : image_spaces) {
1010      std::string location = image_space->GetImageLocation();
1011      std::unique_ptr<ImageHeader> image_header(
1012          gc::space::ImageSpace::ReadImageHeaderOrDie(location.c_str(), isa));
1013      checksum ^= image_header->GetOatChecksum();
1014    }
1015  }
1016  return checksum;
1017}
1018
1019uint32_t OatFileAssistant::GetCombinedImageChecksum() {
1020  if (!image_info_load_attempted_) {
1021    GetImageInfo();
1022  }
1023  return combined_image_checksum_;
1024}
1025
1026gc::space::ImageSpace* OatFileAssistant::OpenImageSpace(const OatFile* oat_file) {
1027  DCHECK(oat_file != nullptr);
1028  std::string art_file = ArtFileName(oat_file);
1029  if (art_file.empty()) {
1030    return nullptr;
1031  }
1032  std::string error_msg;
1033  ScopedObjectAccess soa(Thread::Current());
1034  gc::space::ImageSpace* ret = gc::space::ImageSpace::CreateFromAppImage(art_file.c_str(),
1035                                                                         oat_file,
1036                                                                         &error_msg);
1037  if (ret == nullptr && (VLOG_IS_ON(image) || OS::FileExists(art_file.c_str()))) {
1038    LOG(INFO) << "Failed to open app image " << art_file.c_str() << " " << error_msg;
1039  }
1040  return ret;
1041}
1042
1043}  // namespace art
1044
1045