Home | History | Annotate | Download | only in runtime
      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 
     45 namespace art {
     46 
     47 std::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 
     65 OatFileAssistant::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 
     72 OatFileAssistant::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 
     96 OatFileAssistant::~OatFileAssistant() {
     97   // Clean up the lock file.
     98   if (flock_.HasFile()) {
     99     unlink(flock_.GetFile()->GetPath().c_str());
    100   }
    101 }
    102 
    103 bool 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 
    120 bool 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 
    137 bool 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 
    146 bool 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 
    155 OatFileAssistant::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 
    201 bool OatFileAssistant::IsUpToDate() {
    202   return OatFileIsUpToDate() || OdexFileIsUpToDate();
    203 }
    204 
    205 OatFileAssistant::ResultOfAttemptToUpdate
    206 OatFileAssistant::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 
    216 std::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 
    268 std::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 
    308 bool 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 
    316 const 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 
    332 bool OatFileAssistant::OdexFileExists() {
    333   return GetOdexFile() != nullptr;
    334 }
    335 
    336 OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() {
    337   if (OdexFileIsOutOfDate()) {
    338     return kOatOutOfDate;
    339   }
    340   if (OdexFileIsUpToDate()) {
    341     return kOatUpToDate;
    342   }
    343   return kOatNeedsRelocation;
    344 }
    345 
    346 bool 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 
    359 bool OatFileAssistant::OdexFileNeedsRelocation() {
    360   return OdexFileStatus() == kOatNeedsRelocation;
    361 }
    362 
    363 bool 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 
    376 CompilerFilter::Filter OatFileAssistant::OdexFileCompilerFilter() {
    377   const OatFile* odex_file = GetOdexFile();
    378   CHECK(odex_file != nullptr);
    379 
    380   return odex_file->GetCompilerFilter();
    381 }
    382 std::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 
    393 const 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 
    416 bool OatFileAssistant::OatFileExists() {
    417   return GetOatFile() != nullptr;
    418 }
    419 
    420 OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() {
    421   if (OatFileIsOutOfDate()) {
    422     return kOatOutOfDate;
    423   }
    424   if (OatFileIsUpToDate()) {
    425     return kOatUpToDate;
    426   }
    427   return kOatNeedsRelocation;
    428 }
    429 
    430 bool 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 
    443 bool OatFileAssistant::OatFileNeedsRelocation() {
    444   return OatFileStatus() == kOatNeedsRelocation;
    445 }
    446 
    447 bool 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 
    460 CompilerFilter::Filter OatFileAssistant::OatFileCompilerFilter() {
    461   const OatFile* oat_file = GetOatFile();
    462   CHECK(oat_file != nullptr);
    463 
    464   return oat_file->GetCompilerFilter();
    465 }
    466 
    467 OatFileAssistant::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 
    480 bool 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 
    569 bool OatFileAssistant::GivenOatFileNeedsRelocation(const OatFile& file) {
    570   return GivenOatFileStatus(file) == kOatNeedsRelocation;
    571 }
    572 
    573 bool 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 
    620 OatFileAssistant::ResultOfAttemptToUpdate
    621 OatFileAssistant::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 
    672 OatFileAssistant::ResultOfAttemptToUpdate
    673 OatFileAssistant::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 
    738 bool 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 
    789 bool 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 
    829 std::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 
    847 std::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 
    857 const 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 
    886 const 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 
    910 bool OatFileAssistant::OdexFileIsExecutable() {
    911   const OatFile* odex_file = GetOdexFile();
    912   return (odex_file != nullptr && odex_file->IsExecutable());
    913 }
    914 
    915 bool OatFileAssistant::OdexFileHasPatchInfo() {
    916   const OatFile* odex_file = GetOdexFile();
    917   return (odex_file != nullptr && odex_file->HasPatchInfo());
    918 }
    919 
    920 void 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 
    927 const 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 
    951 bool OatFileAssistant::OatFileIsExecutable() {
    952   const OatFile* oat_file = GetOatFile();
    953   return (oat_file != nullptr && oat_file->IsExecutable());
    954 }
    955 
    956 bool OatFileAssistant::OatFileHasPatchInfo() {
    957   const OatFile* oat_file = GetOatFile();
    958   return (oat_file != nullptr && oat_file->HasPatchInfo());
    959 }
    960 
    961 void 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 
    968 const 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.
   1000 uint32_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 
   1019 uint32_t OatFileAssistant::GetCombinedImageChecksum() {
   1020   if (!image_info_load_attempted_) {
   1021     GetImageInfo();
   1022   }
   1023   return combined_image_checksum_;
   1024 }
   1025 
   1026 gc::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