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 <sstream>
     20 
     21 #include <sys/stat.h>
     22 
     23 #include "android-base/stringprintf.h"
     24 #include "android-base/strings.h"
     25 
     26 #include "base/file_utils.h"
     27 #include "base/logging.h"  // For VLOG.
     28 #include "base/macros.h"
     29 #include "base/os.h"
     30 #include "base/stl_util.h"
     31 #include "base/utils.h"
     32 #include "class_linker.h"
     33 #include "compiler_filter.h"
     34 #include "dex/art_dex_file_loader.h"
     35 #include "dex/dex_file_loader.h"
     36 #include "exec_utils.h"
     37 #include "gc/heap.h"
     38 #include "gc/space/image_space.h"
     39 #include "hidden_api.h"
     40 #include "image.h"
     41 #include "oat.h"
     42 #include "runtime.h"
     43 #include "scoped_thread_state_change-inl.h"
     44 #include "vdex_file.h"
     45 #include "class_loader_context.h"
     46 
     47 namespace art {
     48 
     49 using android::base::StringPrintf;
     50 
     51 std::ostream& operator << (std::ostream& stream, const OatFileAssistant::OatStatus status) {
     52   switch (status) {
     53     case OatFileAssistant::kOatCannotOpen:
     54       stream << "kOatCannotOpen";
     55       break;
     56     case OatFileAssistant::kOatDexOutOfDate:
     57       stream << "kOatDexOutOfDate";
     58       break;
     59     case OatFileAssistant::kOatBootImageOutOfDate:
     60       stream << "kOatBootImageOutOfDate";
     61       break;
     62     case OatFileAssistant::kOatRelocationOutOfDate:
     63       stream << "kOatRelocationOutOfDate";
     64       break;
     65     case OatFileAssistant::kOatUpToDate:
     66       stream << "kOatUpToDate";
     67       break;
     68     default:
     69       UNREACHABLE();
     70   }
     71 
     72   return stream;
     73 }
     74 
     75 OatFileAssistant::OatFileAssistant(const char* dex_location,
     76                                    const InstructionSet isa,
     77                                    bool load_executable,
     78                                    bool only_load_system_executable)
     79     : OatFileAssistant(dex_location,
     80                        isa,
     81                        load_executable,
     82                        only_load_system_executable,
     83                        -1 /* vdex_fd */,
     84                        -1 /* oat_fd */,
     85                        -1 /* zip_fd */) {}
     86 
     87 
     88 OatFileAssistant::OatFileAssistant(const char* dex_location,
     89                                    const InstructionSet isa,
     90                                    bool load_executable,
     91                                    bool only_load_system_executable,
     92                                    int vdex_fd,
     93                                    int oat_fd,
     94                                    int zip_fd)
     95     : isa_(isa),
     96       load_executable_(load_executable),
     97       only_load_system_executable_(only_load_system_executable),
     98       odex_(this, /*is_oat_location*/ false),
     99       oat_(this, /*is_oat_location*/ true),
    100       zip_fd_(zip_fd) {
    101   CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location";
    102 
    103   if (zip_fd < 0) {
    104     CHECK_LE(oat_fd, 0) << "zip_fd must be provided with valid oat_fd. zip_fd=" << zip_fd
    105       << " oat_fd=" << oat_fd;
    106     CHECK_LE(vdex_fd, 0) << "zip_fd must be provided with valid vdex_fd. zip_fd=" << zip_fd
    107       << " vdex_fd=" << vdex_fd;;
    108   }
    109 
    110   dex_location_.assign(dex_location);
    111 
    112   if (load_executable_ && isa != kRuntimeISA) {
    113     LOG(WARNING) << "OatFileAssistant: Load executable specified, "
    114       << "but isa is not kRuntimeISA. Will not attempt to load executable.";
    115     load_executable_ = false;
    116   }
    117 
    118   // Get the odex filename.
    119   std::string error_msg;
    120   std::string odex_file_name;
    121   if (DexLocationToOdexFilename(dex_location_, isa_, &odex_file_name, &error_msg)) {
    122     odex_.Reset(odex_file_name, UseFdToReadFiles(), zip_fd, vdex_fd, oat_fd);
    123   } else {
    124     LOG(WARNING) << "Failed to determine odex file name: " << error_msg;
    125   }
    126 
    127   if (!UseFdToReadFiles()) {
    128     // Get the oat filename.
    129     std::string oat_file_name;
    130     if (DexLocationToOatFilename(dex_location_, isa_, &oat_file_name, &error_msg)) {
    131       oat_.Reset(oat_file_name, false /* use_fd */);
    132     } else {
    133       LOG(WARNING) << "Failed to determine oat file name for dex location "
    134                    << dex_location_ << ": " << error_msg;
    135     }
    136   }
    137 
    138   // Check if the dex directory is writable.
    139   // This will be needed in most uses of OatFileAssistant and so it's OK to
    140   // compute it eagerly. (the only use which will not make use of it is
    141   // OatFileAssistant::GetStatusDump())
    142   size_t pos = dex_location_.rfind('/');
    143   if (pos == std::string::npos) {
    144     LOG(WARNING) << "Failed to determine dex file parent directory: " << dex_location_;
    145   } else if (!UseFdToReadFiles()) {
    146     // We cannot test for parent access when using file descriptors. That's ok
    147     // because in this case we will always pick the odex file anyway.
    148     std::string parent = dex_location_.substr(0, pos);
    149     if (access(parent.c_str(), W_OK) == 0) {
    150       dex_parent_writable_ = true;
    151     } else {
    152       VLOG(oat) << "Dex parent of " << dex_location_ << " is not writable: " << strerror(errno);
    153     }
    154   }
    155 }
    156 
    157 OatFileAssistant::~OatFileAssistant() {
    158   // Clean up the lock file.
    159   if (flock_.get() != nullptr) {
    160     unlink(flock_->GetPath().c_str());
    161   }
    162 }
    163 
    164 bool OatFileAssistant::UseFdToReadFiles() {
    165   return zip_fd_ >= 0;
    166 }
    167 
    168 bool OatFileAssistant::IsInBootClassPath() {
    169   // Note: We check the current boot class path, regardless of the ISA
    170   // specified by the user. This is okay, because the boot class path should
    171   // be the same for all ISAs.
    172   // TODO: Can we verify the boot class path is the same for all ISAs?
    173   Runtime* runtime = Runtime::Current();
    174   ClassLinker* class_linker = runtime->GetClassLinker();
    175   const auto& boot_class_path = class_linker->GetBootClassPath();
    176   for (size_t i = 0; i < boot_class_path.size(); i++) {
    177     if (boot_class_path[i]->GetLocation() == dex_location_) {
    178       VLOG(oat) << "Dex location " << dex_location_ << " is in boot class path";
    179       return true;
    180     }
    181   }
    182   return false;
    183 }
    184 
    185 bool OatFileAssistant::Lock(std::string* error_msg) {
    186   CHECK(error_msg != nullptr);
    187   CHECK(flock_.get() == nullptr) << "OatFileAssistant::Lock already acquired";
    188 
    189   // Note the lock will only succeed for secondary dex files and in test
    190   // environment.
    191   //
    192   // The lock *will fail* for all primary apks in a production environment.
    193   // The app does not have permissions to create locks next to its dex location
    194   // (be it system, data or vendor parition). We also cannot use the odex or
    195   // oat location for the same reasoning.
    196   //
    197   // This is best effort and if it fails it's unlikely that we will be able
    198   // to generate oat files anyway.
    199   std::string lock_file_name = dex_location_ + "." + GetInstructionSetString(isa_) + ".flock";
    200 
    201   flock_ = LockedFile::Open(lock_file_name.c_str(), error_msg);
    202   if (flock_.get() == nullptr) {
    203     unlink(lock_file_name.c_str());
    204     return false;
    205   }
    206   return true;
    207 }
    208 
    209 int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target,
    210                                       bool profile_changed,
    211                                       bool downgrade,
    212                                       ClassLoaderContext* class_loader_context) {
    213   OatFileInfo& info = GetBestInfo();
    214   DexOptNeeded dexopt_needed = info.GetDexOptNeeded(target,
    215                                                     profile_changed,
    216                                                     downgrade,
    217                                                     class_loader_context);
    218   if (info.IsOatLocation() || dexopt_needed == kDex2OatFromScratch) {
    219     return dexopt_needed;
    220   }
    221   return -dexopt_needed;
    222 }
    223 
    224 // Figure out the currently specified compile filter option in the runtime.
    225 // Returns true on success, false if the compiler filter is invalid, in which
    226 // case error_msg describes the problem.
    227 static bool GetRuntimeCompilerFilterOption(CompilerFilter::Filter* filter,
    228                                            std::string* error_msg) {
    229   CHECK(filter != nullptr);
    230   CHECK(error_msg != nullptr);
    231 
    232   *filter = OatFileAssistant::kDefaultCompilerFilterForDexLoading;
    233   for (StringPiece option : Runtime::Current()->GetCompilerOptions()) {
    234     if (option.starts_with("--compiler-filter=")) {
    235       const char* compiler_filter_string = option.substr(strlen("--compiler-filter=")).data();
    236       if (!CompilerFilter::ParseCompilerFilter(compiler_filter_string, filter)) {
    237         *error_msg = std::string("Unknown --compiler-filter value: ")
    238                    + std::string(compiler_filter_string);
    239         return false;
    240       }
    241     }
    242   }
    243   return true;
    244 }
    245 
    246 bool OatFileAssistant::IsUpToDate() {
    247   return GetBestInfo().Status() == kOatUpToDate;
    248 }
    249 
    250 OatFileAssistant::ResultOfAttemptToUpdate
    251 OatFileAssistant::MakeUpToDate(bool profile_changed,
    252                                ClassLoaderContext* class_loader_context,
    253                                std::string* error_msg) {
    254   // The method doesn't use zip_fd_ and directly opens dex files at dex_locations_.
    255   CHECK_EQ(-1, zip_fd_) << "MakeUpToDate should not be called with zip_fd";
    256 
    257   CompilerFilter::Filter target;
    258   if (!GetRuntimeCompilerFilterOption(&target, error_msg)) {
    259     return kUpdateNotAttempted;
    260   }
    261 
    262   OatFileInfo& info = GetBestInfo();
    263   // TODO(calin, jeffhao): the context should really be passed to GetDexOptNeeded: b/62269291.
    264   // This is actually not trivial in the current logic as it will interact with the collision
    265   // check:
    266   //   - currently, if the context does not match but we have no collisions we still accept the
    267   //     oat file.
    268   //   - if GetDexOptNeeded would return kDex2OatFromScratch for a context mismatch and we make
    269   //     the oat code up to date the collision check becomes useless.
    270   //   - however, MakeUpToDate will not always succeed (e.g. for primary apks, or for dex files
    271   //     loaded in other processes). So it boils down to how far do we want to complicate
    272   //     the logic in order to enable the use of oat files. Maybe its time to try simplify it.
    273   switch (info.GetDexOptNeeded(
    274         target, profile_changed, /*downgrade*/ false, class_loader_context)) {
    275     case kNoDexOptNeeded:
    276       return kUpdateSucceeded;
    277 
    278     // TODO: For now, don't bother with all the different ways we can call
    279     // dex2oat to generate the oat file. Always generate the oat file as if it
    280     // were kDex2OatFromScratch.
    281     case kDex2OatFromScratch:
    282     case kDex2OatForBootImage:
    283     case kDex2OatForRelocation:
    284     case kDex2OatForFilter:
    285       return GenerateOatFileNoChecks(info, target, class_loader_context, error_msg);
    286   }
    287   UNREACHABLE();
    288 }
    289 
    290 std::unique_ptr<OatFile> OatFileAssistant::GetBestOatFile() {
    291   return GetBestInfo().ReleaseFileForUse();
    292 }
    293 
    294 std::string OatFileAssistant::GetStatusDump() {
    295   std::ostringstream status;
    296   bool oat_file_exists = false;
    297   bool odex_file_exists = false;
    298   if (oat_.Status() != kOatCannotOpen) {
    299     // If we can open the file, Filename should not return null.
    300     CHECK(oat_.Filename() != nullptr);
    301 
    302     oat_file_exists = true;
    303     status << *oat_.Filename() << "[status=" << oat_.Status() << ", ";
    304     const OatFile* file = oat_.GetFile();
    305     if (file == nullptr) {
    306       // If the file is null even though the status is not kOatCannotOpen, it
    307       // means we must have a vdex file with no corresponding oat file. In
    308       // this case we cannot determine the compilation filter. Indicate that
    309       // we have only the vdex file instead.
    310       status << "vdex-only";
    311     } else {
    312       status << "compilation_filter=" << CompilerFilter::NameOfFilter(file->GetCompilerFilter());
    313     }
    314   }
    315 
    316   if (odex_.Status() != kOatCannotOpen) {
    317     // If we can open the file, Filename should not return null.
    318     CHECK(odex_.Filename() != nullptr);
    319 
    320     odex_file_exists = true;
    321     if (oat_file_exists) {
    322       status << "] ";
    323     }
    324     status << *odex_.Filename() << "[status=" << odex_.Status() << ", ";
    325     const OatFile* file = odex_.GetFile();
    326     if (file == nullptr) {
    327       status << "vdex-only";
    328     } else {
    329       status << "compilation_filter=" << CompilerFilter::NameOfFilter(file->GetCompilerFilter());
    330     }
    331   }
    332 
    333   if (!oat_file_exists && !odex_file_exists) {
    334     status << "invalid[";
    335   }
    336 
    337   status << "]";
    338   return status.str();
    339 }
    340 
    341 std::vector<std::unique_ptr<const DexFile>> OatFileAssistant::LoadDexFiles(
    342     const OatFile &oat_file, const char *dex_location) {
    343   std::vector<std::unique_ptr<const DexFile>> dex_files;
    344   if (LoadDexFiles(oat_file, dex_location, &dex_files)) {
    345     return dex_files;
    346   } else {
    347     return std::vector<std::unique_ptr<const DexFile>>();
    348   }
    349 }
    350 
    351 bool OatFileAssistant::LoadDexFiles(
    352     const OatFile &oat_file,
    353     const std::string& dex_location,
    354     std::vector<std::unique_ptr<const DexFile>>* out_dex_files) {
    355   // Load the main dex file.
    356   std::string error_msg;
    357   const OatFile::OatDexFile* oat_dex_file = oat_file.GetOatDexFile(
    358       dex_location.c_str(), nullptr, &error_msg);
    359   if (oat_dex_file == nullptr) {
    360     LOG(WARNING) << error_msg;
    361     return false;
    362   }
    363 
    364   std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg);
    365   if (dex_file.get() == nullptr) {
    366     LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
    367     return false;
    368   }
    369   out_dex_files->push_back(std::move(dex_file));
    370 
    371   // Load the rest of the multidex entries
    372   for (size_t i = 1;; i++) {
    373     std::string multidex_dex_location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str());
    374     oat_dex_file = oat_file.GetOatDexFile(multidex_dex_location.c_str(), nullptr);
    375     if (oat_dex_file == nullptr) {
    376       // There are no more multidex entries to load.
    377       break;
    378     }
    379 
    380     dex_file = oat_dex_file->OpenDexFile(&error_msg);
    381     if (dex_file.get() == nullptr) {
    382       LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg;
    383       return false;
    384     }
    385     out_dex_files->push_back(std::move(dex_file));
    386   }
    387   return true;
    388 }
    389 
    390 bool OatFileAssistant::HasOriginalDexFiles() {
    391   // Ensure GetRequiredDexChecksums has been run so that
    392   // has_original_dex_files_ is initialized. We don't care about the result of
    393   // GetRequiredDexChecksums.
    394   GetRequiredDexChecksums();
    395   return has_original_dex_files_;
    396 }
    397 
    398 OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() {
    399   return odex_.Status();
    400 }
    401 
    402 OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() {
    403   return oat_.Status();
    404 }
    405 
    406 bool OatFileAssistant::DexChecksumUpToDate(const VdexFile& file, std::string* error_msg) {
    407   const std::vector<uint32_t>* required_dex_checksums = GetRequiredDexChecksums();
    408   if (required_dex_checksums == nullptr) {
    409     LOG(WARNING) << "Required dex checksums not found. Assuming dex checksums are up to date.";
    410     return true;
    411   }
    412 
    413   uint32_t number_of_dex_files = file.GetVerifierDepsHeader().GetNumberOfDexFiles();
    414   if (required_dex_checksums->size() != number_of_dex_files) {
    415     *error_msg = StringPrintf("expected %zu dex files but found %u",
    416                               required_dex_checksums->size(),
    417                               number_of_dex_files);
    418     return false;
    419   }
    420 
    421   for (uint32_t i = 0; i < number_of_dex_files; i++) {
    422     uint32_t expected_checksum = (*required_dex_checksums)[i];
    423     uint32_t actual_checksum = file.GetLocationChecksum(i);
    424     if (expected_checksum != actual_checksum) {
    425       std::string dex = DexFileLoader::GetMultiDexLocation(i, dex_location_.c_str());
    426       *error_msg = StringPrintf("Dex checksum does not match for dex: %s."
    427                                 "Expected: %u, actual: %u",
    428                                 dex.c_str(),
    429                                 expected_checksum,
    430                                 actual_checksum);
    431       return false;
    432     }
    433   }
    434 
    435   return true;
    436 }
    437 
    438 bool OatFileAssistant::DexChecksumUpToDate(const OatFile& file, std::string* error_msg) {
    439   const std::vector<uint32_t>* required_dex_checksums = GetRequiredDexChecksums();
    440   if (required_dex_checksums == nullptr) {
    441     LOG(WARNING) << "Required dex checksums not found. Assuming dex checksums are up to date.";
    442     return true;
    443   }
    444 
    445   uint32_t number_of_dex_files = file.GetOatHeader().GetDexFileCount();
    446   if (required_dex_checksums->size() != number_of_dex_files) {
    447     *error_msg = StringPrintf("expected %zu dex files but found %u",
    448                               required_dex_checksums->size(),
    449                               number_of_dex_files);
    450     return false;
    451   }
    452 
    453   for (uint32_t i = 0; i < number_of_dex_files; i++) {
    454     std::string dex = DexFileLoader::GetMultiDexLocation(i, dex_location_.c_str());
    455     uint32_t expected_checksum = (*required_dex_checksums)[i];
    456     const OatFile::OatDexFile* oat_dex_file = file.GetOatDexFile(dex.c_str(), nullptr);
    457     if (oat_dex_file == nullptr) {
    458       *error_msg = StringPrintf("failed to find %s in %s", dex.c_str(), file.GetLocation().c_str());
    459       return false;
    460     }
    461     uint32_t actual_checksum = oat_dex_file->GetDexFileLocationChecksum();
    462     if (expected_checksum != actual_checksum) {
    463       VLOG(oat) << "Dex checksum does not match for dex: " << dex
    464         << ". Expected: " << expected_checksum
    465         << ", Actual: " << actual_checksum;
    466       return false;
    467     }
    468   }
    469   return true;
    470 }
    471 
    472 OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) {
    473   // Verify the ART_USE_READ_BARRIER state.
    474   // TODO: Don't fully reject files due to read barrier state. If they contain
    475   // compiled code and are otherwise okay, we should return something like
    476   // kOatRelocationOutOfDate. If they don't contain compiled code, the read
    477   // barrier state doesn't matter.
    478   const bool is_cc = file.GetOatHeader().IsConcurrentCopying();
    479   constexpr bool kRuntimeIsCC = kUseReadBarrier;
    480   if (is_cc != kRuntimeIsCC) {
    481     return kOatCannotOpen;
    482   }
    483 
    484   // Verify the dex checksum.
    485   std::string error_msg;
    486   VdexFile* vdex = file.GetVdexFile();
    487   if (!DexChecksumUpToDate(*vdex, &error_msg)) {
    488     LOG(ERROR) << error_msg;
    489     return kOatDexOutOfDate;
    490   }
    491 
    492   CompilerFilter::Filter current_compiler_filter = file.GetCompilerFilter();
    493 
    494   // Verify the image checksum
    495   if (CompilerFilter::DependsOnImageChecksum(current_compiler_filter)) {
    496     const ImageInfo* image_info = GetImageInfo();
    497     if (image_info == nullptr) {
    498       VLOG(oat) << "No image for oat image checksum to match against.";
    499 
    500       if (HasOriginalDexFiles()) {
    501         return kOatBootImageOutOfDate;
    502       }
    503 
    504       // If there is no original dex file to fall back to, grudgingly accept
    505       // the oat file. This could technically lead to crashes, but there's no
    506       // way we could find a better oat file to use for this dex location,
    507       // and it's better than being stuck in a boot loop with no way out.
    508       // The problem will hopefully resolve itself the next time the runtime
    509       // starts up.
    510       LOG(WARNING) << "Dex location " << dex_location_ << " does not seem to include dex file. "
    511         << "Allow oat file use. This is potentially dangerous.";
    512     } else if (file.GetOatHeader().GetImageFileLocationOatChecksum() != image_info->oat_checksum) {
    513       VLOG(oat) << "Oat image checksum does not match image checksum.";
    514       return kOatBootImageOutOfDate;
    515     }
    516   } else {
    517     VLOG(oat) << "Image checksum test skipped for compiler filter " << current_compiler_filter;
    518   }
    519 
    520   // zip_file_only_contains_uncompressed_dex_ is only set during fetching the dex checksums.
    521   DCHECK(required_dex_checksums_attempted_);
    522   if (only_load_system_executable_ &&
    523       !LocationIsOnSystem(file.GetLocation().c_str()) &&
    524       file.ContainsDexCode() &&
    525       zip_file_only_contains_uncompressed_dex_) {
    526     LOG(ERROR) << "Not loading "
    527                << dex_location_
    528                << ": oat file has dex code, but APK has uncompressed dex code";
    529     return kOatDexOutOfDate;
    530   }
    531 
    532   if (CompilerFilter::IsAotCompilationEnabled(current_compiler_filter)) {
    533     if (!file.IsPic()) {
    534       const ImageInfo* image_info = GetImageInfo();
    535       if (image_info == nullptr) {
    536         VLOG(oat) << "No image to check oat relocation against.";
    537         return kOatRelocationOutOfDate;
    538       }
    539 
    540       // Verify the oat_data_begin recorded for the image in the oat file matches
    541       // the actual oat_data_begin for boot.oat in the image.
    542       const OatHeader& oat_header = file.GetOatHeader();
    543       uintptr_t oat_data_begin = oat_header.GetImageFileLocationOatDataBegin();
    544       if (oat_data_begin != image_info->oat_data_begin) {
    545         VLOG(oat) << file.GetLocation() <<
    546           ": Oat file image oat_data_begin (" << oat_data_begin << ")"
    547           << " does not match actual image oat_data_begin ("
    548           << image_info->oat_data_begin << ")";
    549         return kOatRelocationOutOfDate;
    550       }
    551 
    552       // Verify the oat_patch_delta recorded for the image in the oat file matches
    553       // the actual oat_patch_delta for the image.
    554       int32_t oat_patch_delta = oat_header.GetImagePatchDelta();
    555       if (oat_patch_delta != image_info->patch_delta) {
    556         VLOG(oat) << file.GetLocation() <<
    557           ": Oat file image patch delta (" << oat_patch_delta << ")"
    558           << " does not match actual image patch delta ("
    559           << image_info->patch_delta << ")";
    560         return kOatRelocationOutOfDate;
    561       }
    562     } else {
    563       // Oat files compiled in PIC mode do not require relocation.
    564       VLOG(oat) << "Oat relocation test skipped for PIC oat file";
    565     }
    566   } else {
    567     VLOG(oat) << "Oat relocation test skipped for compiler filter " << current_compiler_filter;
    568   }
    569   return kOatUpToDate;
    570 }
    571 
    572 static bool DexLocationToOdexNames(const std::string& location,
    573                                    InstructionSet isa,
    574                                    std::string* odex_filename,
    575                                    std::string* oat_dir,
    576                                    std::string* isa_dir,
    577                                    std::string* error_msg) {
    578   CHECK(odex_filename != nullptr);
    579   CHECK(error_msg != nullptr);
    580 
    581   // The odex file name is formed by replacing the dex_location extension with
    582   // .odex and inserting an oat/<isa> directory. For example:
    583   //   location = /foo/bar/baz.jar
    584   //   odex_location = /foo/bar/oat/<isa>/baz.odex
    585 
    586   // Find the directory portion of the dex location and add the oat/<isa>
    587   // directory.
    588   size_t pos = location.rfind('/');
    589   if (pos == std::string::npos) {
    590     *error_msg = "Dex location " + location + " has no directory.";
    591     return false;
    592   }
    593   std::string dir = location.substr(0, pos+1);
    594   // Add the oat directory.
    595   dir += "oat";
    596   if (oat_dir != nullptr) {
    597     *oat_dir = dir;
    598   }
    599   // Add the isa directory
    600   dir += "/" + std::string(GetInstructionSetString(isa));
    601   if (isa_dir != nullptr) {
    602     *isa_dir = dir;
    603   }
    604 
    605   // Get the base part of the file without the extension.
    606   std::string file = location.substr(pos+1);
    607   pos = file.rfind('.');
    608   if (pos == std::string::npos) {
    609     *error_msg = "Dex location " + location + " has no extension.";
    610     return false;
    611   }
    612   std::string base = file.substr(0, pos);
    613 
    614   *odex_filename = dir + "/" + base + ".odex";
    615   return true;
    616 }
    617 
    618 // Prepare a subcomponent of the odex directory.
    619 // (i.e. create and set the expected permissions on the path `dir`).
    620 static bool PrepareDirectory(const std::string& dir, std::string* error_msg) {
    621   struct stat dir_stat;
    622   if (TEMP_FAILURE_RETRY(stat(dir.c_str(), &dir_stat)) == 0) {
    623     // The directory exists. Check if it is indeed a directory.
    624     if (!S_ISDIR(dir_stat.st_mode)) {
    625       *error_msg = dir + " is not a dir";
    626       return false;
    627     } else {
    628       // The dir is already on disk.
    629       return true;
    630     }
    631   }
    632 
    633   // Failed to stat. We need to create the directory.
    634   if (errno != ENOENT) {
    635     *error_msg = "Could not stat isa dir " + dir + ":" + strerror(errno);
    636     return false;
    637   }
    638 
    639   mode_t mode = S_IRWXU | S_IXGRP | S_IXOTH;
    640   if (mkdir(dir.c_str(), mode) != 0) {
    641     *error_msg = "Could not create dir " + dir + ":" + strerror(errno);
    642     return false;
    643   }
    644   if (chmod(dir.c_str(), mode) != 0) {
    645     *error_msg = "Could not create the oat dir " + dir + ":" + strerror(errno);
    646     return false;
    647   }
    648   return true;
    649 }
    650 
    651 // Prepares the odex directory for the given dex location.
    652 static bool PrepareOdexDirectories(const std::string& dex_location,
    653                                    const std::string& expected_odex_location,
    654                                    InstructionSet isa,
    655                                    std::string* error_msg) {
    656   std::string actual_odex_location;
    657   std::string oat_dir;
    658   std::string isa_dir;
    659   if (!DexLocationToOdexNames(
    660         dex_location, isa, &actual_odex_location, &oat_dir, &isa_dir, error_msg)) {
    661     return false;
    662   }
    663   DCHECK_EQ(expected_odex_location, actual_odex_location);
    664 
    665   if (!PrepareDirectory(oat_dir, error_msg)) {
    666     return false;
    667   }
    668   if (!PrepareDirectory(isa_dir, error_msg)) {
    669     return false;
    670   }
    671   return true;
    672 }
    673 
    674 class Dex2oatFileWrapper {
    675  public:
    676   explicit Dex2oatFileWrapper(File* file)
    677       : file_(file),
    678         unlink_file_at_destruction_(true) {
    679   }
    680 
    681   ~Dex2oatFileWrapper() {
    682     if (unlink_file_at_destruction_ && (file_ != nullptr)) {
    683       file_->Erase(/*unlink*/ true);
    684     }
    685   }
    686 
    687   File* GetFile() { return file_.get(); }
    688 
    689   void DisableUnlinkAtDestruction() {
    690     unlink_file_at_destruction_ = false;
    691   }
    692 
    693  private:
    694   std::unique_ptr<File> file_;
    695   bool unlink_file_at_destruction_;
    696 };
    697 
    698 OatFileAssistant::ResultOfAttemptToUpdate OatFileAssistant::GenerateOatFileNoChecks(
    699       OatFileAssistant::OatFileInfo& info,
    700       CompilerFilter::Filter filter,
    701       const ClassLoaderContext* class_loader_context,
    702       std::string* error_msg) {
    703   CHECK(error_msg != nullptr);
    704 
    705   Runtime* runtime = Runtime::Current();
    706   if (!runtime->IsDex2OatEnabled()) {
    707     *error_msg = "Generation of oat file for dex location " + dex_location_
    708       + " not attempted because dex2oat is disabled.";
    709     return kUpdateNotAttempted;
    710   }
    711 
    712   if (info.Filename() == nullptr) {
    713     *error_msg = "Generation of oat file for dex location " + dex_location_
    714       + " not attempted because the oat file name could not be determined.";
    715     return kUpdateNotAttempted;
    716   }
    717   const std::string& oat_file_name = *info.Filename();
    718   const std::string& vdex_file_name = GetVdexFilename(oat_file_name);
    719 
    720   // dex2oat ignores missing dex files and doesn't report an error.
    721   // Check explicitly here so we can detect the error properly.
    722   // TODO: Why does dex2oat behave that way?
    723   struct stat dex_path_stat;
    724   if (TEMP_FAILURE_RETRY(stat(dex_location_.c_str(), &dex_path_stat)) != 0) {
    725     *error_msg = "Could not access dex location " + dex_location_ + ":" + strerror(errno);
    726     return kUpdateNotAttempted;
    727   }
    728 
    729   // If this is the odex location, we need to create the odex file layout (../oat/isa/..)
    730   if (!info.IsOatLocation()) {
    731     if (!PrepareOdexDirectories(dex_location_, oat_file_name, isa_, error_msg)) {
    732       return kUpdateNotAttempted;
    733     }
    734   }
    735 
    736   // Set the permissions for the oat and the vdex files.
    737   // The user always gets read and write while the group and others propagate
    738   // the reading access of the original dex file.
    739   mode_t file_mode = S_IRUSR | S_IWUSR |
    740       (dex_path_stat.st_mode & S_IRGRP) |
    741       (dex_path_stat.st_mode & S_IROTH);
    742 
    743   Dex2oatFileWrapper vdex_file_wrapper(OS::CreateEmptyFile(vdex_file_name.c_str()));
    744   File* vdex_file = vdex_file_wrapper.GetFile();
    745   if (vdex_file == nullptr) {
    746     *error_msg = "Generation of oat file " + oat_file_name
    747       + " not attempted because the vdex file " + vdex_file_name
    748       + " could not be opened.";
    749     return kUpdateNotAttempted;
    750   }
    751 
    752   if (fchmod(vdex_file->Fd(), file_mode) != 0) {
    753     *error_msg = "Generation of oat file " + oat_file_name
    754       + " not attempted because the vdex file " + vdex_file_name
    755       + " could not be made world readable.";
    756     return kUpdateNotAttempted;
    757   }
    758 
    759   Dex2oatFileWrapper oat_file_wrapper(OS::CreateEmptyFile(oat_file_name.c_str()));
    760   File* oat_file = oat_file_wrapper.GetFile();
    761   if (oat_file == nullptr) {
    762     *error_msg = "Generation of oat file " + oat_file_name
    763       + " not attempted because the oat file could not be created.";
    764     return kUpdateNotAttempted;
    765   }
    766 
    767   if (fchmod(oat_file->Fd(), file_mode) != 0) {
    768     *error_msg = "Generation of oat file " + oat_file_name
    769       + " not attempted because the oat file could not be made world readable.";
    770     return kUpdateNotAttempted;
    771   }
    772 
    773   std::vector<std::string> args;
    774   args.push_back("--dex-file=" + dex_location_);
    775   args.push_back("--output-vdex-fd=" + std::to_string(vdex_file->Fd()));
    776   args.push_back("--oat-fd=" + std::to_string(oat_file->Fd()));
    777   args.push_back("--oat-location=" + oat_file_name);
    778   args.push_back("--compiler-filter=" + CompilerFilter::NameOfFilter(filter));
    779   const std::string dex2oat_context = class_loader_context == nullptr
    780         ? OatFile::kSpecialSharedLibrary
    781         : class_loader_context->EncodeContextForDex2oat(/*base_dir*/ "");
    782   args.push_back("--class-loader-context=" + dex2oat_context);
    783 
    784   if (!Dex2Oat(args, error_msg)) {
    785     return kUpdateFailed;
    786   }
    787 
    788   if (vdex_file->FlushCloseOrErase() != 0) {
    789     *error_msg = "Unable to close vdex file " + vdex_file_name;
    790     return kUpdateFailed;
    791   }
    792 
    793   if (oat_file->FlushCloseOrErase() != 0) {
    794     *error_msg = "Unable to close oat file " + oat_file_name;
    795     return kUpdateFailed;
    796   }
    797 
    798   // Mark that the odex file has changed and we should try to reload.
    799   info.Reset();
    800   // We have compiled successfully. Disable the auto-unlink.
    801   vdex_file_wrapper.DisableUnlinkAtDestruction();
    802   oat_file_wrapper.DisableUnlinkAtDestruction();
    803 
    804   return kUpdateSucceeded;
    805 }
    806 
    807 bool OatFileAssistant::Dex2Oat(const std::vector<std::string>& args,
    808                                std::string* error_msg) {
    809   Runtime* runtime = Runtime::Current();
    810   std::string image_location = ImageLocation();
    811   if (image_location.empty()) {
    812     *error_msg = "No image location found for Dex2Oat.";
    813     return false;
    814   }
    815 
    816   std::vector<std::string> argv;
    817   argv.push_back(runtime->GetCompilerExecutable());
    818   if (runtime->IsJavaDebuggable()) {
    819     argv.push_back("--debuggable");
    820   }
    821   runtime->AddCurrentRuntimeFeaturesAsDex2OatArguments(&argv);
    822 
    823   if (!runtime->IsVerificationEnabled()) {
    824     argv.push_back("--compiler-filter=verify-none");
    825   }
    826 
    827   if (runtime->GetHiddenApiEnforcementPolicy() != hiddenapi::EnforcementPolicy::kNoChecks) {
    828     argv.push_back("--runtime-arg");
    829     argv.push_back("-Xhidden-api-checks");
    830   }
    831 
    832   if (runtime->MustRelocateIfPossible()) {
    833     argv.push_back("--runtime-arg");
    834     argv.push_back("-Xrelocate");
    835   } else {
    836     argv.push_back("--runtime-arg");
    837     argv.push_back("-Xnorelocate");
    838   }
    839 
    840   if (!kIsTargetBuild) {
    841     argv.push_back("--host");
    842   }
    843 
    844   argv.push_back("--boot-image=" + image_location);
    845 
    846   std::vector<std::string> compiler_options = runtime->GetCompilerOptions();
    847   argv.insert(argv.end(), compiler_options.begin(), compiler_options.end());
    848 
    849   argv.insert(argv.end(), args.begin(), args.end());
    850 
    851   std::string command_line(android::base::Join(argv, ' '));
    852   return Exec(argv, error_msg);
    853 }
    854 
    855 bool OatFileAssistant::DexLocationToOdexFilename(const std::string& location,
    856                                                  InstructionSet isa,
    857                                                  std::string* odex_filename,
    858                                                  std::string* error_msg) {
    859   return DexLocationToOdexNames(location, isa, odex_filename, nullptr, nullptr, error_msg);
    860 }
    861 
    862 bool OatFileAssistant::DexLocationToOatFilename(const std::string& location,
    863                                                 InstructionSet isa,
    864                                                 std::string* oat_filename,
    865                                                 std::string* error_msg) {
    866   CHECK(oat_filename != nullptr);
    867   CHECK(error_msg != nullptr);
    868 
    869   std::string cache_dir = GetDalvikCache(GetInstructionSetString(isa));
    870   if (cache_dir.empty()) {
    871     *error_msg = "Dalvik cache directory does not exist";
    872     return false;
    873   }
    874 
    875   // TODO: The oat file assistant should be the definitive place for
    876   // determining the oat file name from the dex location, not
    877   // GetDalvikCacheFilename.
    878   return GetDalvikCacheFilename(location.c_str(), cache_dir.c_str(), oat_filename, error_msg);
    879 }
    880 
    881 std::string OatFileAssistant::ImageLocation() {
    882   Runtime* runtime = Runtime::Current();
    883   const std::vector<gc::space::ImageSpace*>& image_spaces =
    884       runtime->GetHeap()->GetBootImageSpaces();
    885   if (image_spaces.empty()) {
    886     return "";
    887   }
    888   return image_spaces[0]->GetImageLocation();
    889 }
    890 
    891 const std::vector<uint32_t>* OatFileAssistant::GetRequiredDexChecksums() {
    892   if (!required_dex_checksums_attempted_) {
    893     required_dex_checksums_attempted_ = true;
    894     required_dex_checksums_found_ = false;
    895     cached_required_dex_checksums_.clear();
    896     std::string error_msg;
    897     const ArtDexFileLoader dex_file_loader;
    898     if (dex_file_loader.GetMultiDexChecksums(dex_location_.c_str(),
    899                                              &cached_required_dex_checksums_,
    900                                              &error_msg,
    901                                              zip_fd_,
    902                                              &zip_file_only_contains_uncompressed_dex_)) {
    903       required_dex_checksums_found_ = true;
    904       has_original_dex_files_ = true;
    905     } else {
    906       // This can happen if the original dex file has been stripped from the
    907       // apk.
    908       VLOG(oat) << "OatFileAssistant: " << error_msg;
    909       has_original_dex_files_ = false;
    910 
    911       // Get the checksums from the odex if we can.
    912       const OatFile* odex_file = odex_.GetFile();
    913       if (odex_file != nullptr) {
    914         required_dex_checksums_found_ = true;
    915         for (size_t i = 0; i < odex_file->GetOatHeader().GetDexFileCount(); i++) {
    916           std::string dex = DexFileLoader::GetMultiDexLocation(i, dex_location_.c_str());
    917           const OatFile::OatDexFile* odex_dex_file = odex_file->GetOatDexFile(dex.c_str(), nullptr);
    918           if (odex_dex_file == nullptr) {
    919             required_dex_checksums_found_ = false;
    920             break;
    921           }
    922           cached_required_dex_checksums_.push_back(odex_dex_file->GetDexFileLocationChecksum());
    923         }
    924       }
    925     }
    926   }
    927   return required_dex_checksums_found_ ? &cached_required_dex_checksums_ : nullptr;
    928 }
    929 
    930 std::unique_ptr<OatFileAssistant::ImageInfo>
    931 OatFileAssistant::ImageInfo::GetRuntimeImageInfo(InstructionSet isa, std::string* error_msg) {
    932   CHECK(error_msg != nullptr);
    933 
    934   Runtime* runtime = Runtime::Current();
    935   std::unique_ptr<ImageInfo> info(new ImageInfo());
    936   info->location = runtime->GetImageLocation();
    937 
    938   std::unique_ptr<ImageHeader> image_header(
    939       gc::space::ImageSpace::ReadImageHeader(info->location.c_str(), isa, error_msg));
    940   if (image_header == nullptr) {
    941     return nullptr;
    942   }
    943 
    944   info->oat_checksum = image_header->GetOatChecksum();
    945   info->oat_data_begin = reinterpret_cast<uintptr_t>(image_header->GetOatDataBegin());
    946   info->patch_delta = image_header->GetPatchDelta();
    947   return info;
    948 }
    949 
    950 const OatFileAssistant::ImageInfo* OatFileAssistant::GetImageInfo() {
    951   if (!image_info_load_attempted_) {
    952     image_info_load_attempted_ = true;
    953     std::string error_msg;
    954     cached_image_info_ = ImageInfo::GetRuntimeImageInfo(isa_, &error_msg);
    955     if (cached_image_info_ == nullptr) {
    956       LOG(WARNING) << "Unable to get runtime image info: " << error_msg;
    957     }
    958   }
    959   return cached_image_info_.get();
    960 }
    961 
    962 OatFileAssistant::OatFileInfo& OatFileAssistant::GetBestInfo() {
    963   // TODO(calin): Document the side effects of class loading when
    964   // running dalvikvm command line.
    965   if (dex_parent_writable_ || UseFdToReadFiles()) {
    966     // If the parent of the dex file is writable it means that we can
    967     // create the odex file. In this case we unconditionally pick the odex
    968     // as the best oat file. This corresponds to the regular use case when
    969     // apps gets installed or when they load private, secondary dex file.
    970     // For apps on the system partition the odex location will not be
    971     // writable and thus the oat location might be more up to date.
    972     return odex_;
    973   }
    974 
    975   // We cannot write to the odex location. This must be a system app.
    976 
    977   // If the oat location is usable take it.
    978   if (oat_.IsUseable()) {
    979     return oat_;
    980   }
    981 
    982   // The oat file is not usable but the odex file might be up to date.
    983   // This is an indication that we are dealing with an up to date prebuilt
    984   // (that doesn't need relocation).
    985   if (odex_.Status() == kOatUpToDate) {
    986     return odex_;
    987   }
    988 
    989   // The oat file is not usable and the odex file is not up to date.
    990   // However we have access to the original dex file which means we can make
    991   // the oat location up to date.
    992   if (HasOriginalDexFiles()) {
    993     return oat_;
    994   }
    995 
    996   // We got into the worst situation here:
    997   // - the oat location is not usable
    998   // - the prebuild odex location is not up to date
    999   // - and we don't have the original dex file anymore (stripped).
   1000   // Pick the odex if it exists, or the oat if not.
   1001   return (odex_.Status() == kOatCannotOpen) ? oat_ : odex_;
   1002 }
   1003 
   1004 std::unique_ptr<gc::space::ImageSpace> OatFileAssistant::OpenImageSpace(const OatFile* oat_file) {
   1005   DCHECK(oat_file != nullptr);
   1006   std::string art_file = ReplaceFileExtension(oat_file->GetLocation(), "art");
   1007   if (art_file.empty()) {
   1008     return nullptr;
   1009   }
   1010   std::string error_msg;
   1011   ScopedObjectAccess soa(Thread::Current());
   1012   std::unique_ptr<gc::space::ImageSpace> ret =
   1013       gc::space::ImageSpace::CreateFromAppImage(art_file.c_str(), oat_file, &error_msg);
   1014   if (ret == nullptr && (VLOG_IS_ON(image) || OS::FileExists(art_file.c_str()))) {
   1015     LOG(INFO) << "Failed to open app image " << art_file.c_str() << " " << error_msg;
   1016   }
   1017   return ret;
   1018 }
   1019 
   1020 OatFileAssistant::OatFileInfo::OatFileInfo(OatFileAssistant* oat_file_assistant,
   1021                                            bool is_oat_location)
   1022   : oat_file_assistant_(oat_file_assistant), is_oat_location_(is_oat_location)
   1023 {}
   1024 
   1025 bool OatFileAssistant::OatFileInfo::IsOatLocation() {
   1026   return is_oat_location_;
   1027 }
   1028 
   1029 const std::string* OatFileAssistant::OatFileInfo::Filename() {
   1030   return filename_provided_ ? &filename_ : nullptr;
   1031 }
   1032 
   1033 bool OatFileAssistant::OatFileInfo::IsUseable() {
   1034   switch (Status()) {
   1035     case kOatCannotOpen:
   1036     case kOatDexOutOfDate:
   1037     case kOatBootImageOutOfDate: return false;
   1038 
   1039     case kOatRelocationOutOfDate:
   1040     case kOatUpToDate: return true;
   1041   }
   1042   UNREACHABLE();
   1043 }
   1044 
   1045 OatFileAssistant::OatStatus OatFileAssistant::OatFileInfo::Status() {
   1046   if (!status_attempted_) {
   1047     status_attempted_ = true;
   1048     const OatFile* file = GetFile();
   1049     if (file == nullptr) {
   1050       // Check to see if there is a vdex file we can make use of.
   1051       std::string error_msg;
   1052       std::string vdex_filename = GetVdexFilename(filename_);
   1053       std::unique_ptr<VdexFile> vdex;
   1054       if (use_fd_) {
   1055         if (vdex_fd_ >= 0) {
   1056           struct stat s;
   1057           int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd_, &s));
   1058           if (rc == -1) {
   1059             error_msg = StringPrintf("Failed getting length of the vdex file %s.", strerror(errno));
   1060           } else {
   1061             vdex = VdexFile::Open(vdex_fd_,
   1062                                   s.st_size,
   1063                                   vdex_filename,
   1064                                   false /*writable*/,
   1065                                   false /*low_4gb*/,
   1066                                   false /* unquicken */,
   1067                                   &error_msg);
   1068           }
   1069         }
   1070       } else {
   1071         vdex = VdexFile::Open(vdex_filename,
   1072                               false /*writeable*/,
   1073                               false /*low_4gb*/,
   1074                               false /*unquicken*/,
   1075                               &error_msg);
   1076       }
   1077       if (vdex == nullptr) {
   1078         status_ = kOatCannotOpen;
   1079         VLOG(oat) << "unable to open vdex file " << vdex_filename << ": " << error_msg;
   1080       } else {
   1081         if (oat_file_assistant_->DexChecksumUpToDate(*vdex, &error_msg)) {
   1082           // The vdex file does not contain enough information to determine
   1083           // whether it is up to date with respect to the boot image, so we
   1084           // assume it is out of date.
   1085           VLOG(oat) << error_msg;
   1086           status_ = kOatBootImageOutOfDate;
   1087         } else {
   1088           status_ = kOatDexOutOfDate;
   1089         }
   1090       }
   1091     } else {
   1092       status_ = oat_file_assistant_->GivenOatFileStatus(*file);
   1093       VLOG(oat) << file->GetLocation() << " is " << status_
   1094           << " with filter " << file->GetCompilerFilter();
   1095     }
   1096   }
   1097   return status_;
   1098 }
   1099 
   1100 OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded(
   1101     CompilerFilter::Filter target,
   1102     bool profile_changed,
   1103     bool downgrade,
   1104     ClassLoaderContext* context) {
   1105 
   1106   bool compilation_desired = CompilerFilter::IsAotCompilationEnabled(target);
   1107   bool filter_okay = CompilerFilterIsOkay(target, profile_changed, downgrade);
   1108   bool class_loader_context_okay = ClassLoaderContextIsOkay(context);
   1109 
   1110   // Only check the filter and relocation if the class loader context is ok.
   1111   // If it is not, we will return kDex2OatFromScratch as the compilation needs to be redone.
   1112   if (class_loader_context_okay) {
   1113     if (filter_okay && Status() == kOatUpToDate) {
   1114       // The oat file is in good shape as is.
   1115       return kNoDexOptNeeded;
   1116     }
   1117 
   1118     if (filter_okay && !compilation_desired && Status() == kOatRelocationOutOfDate) {
   1119       // If no compilation is desired, then it doesn't matter if the oat
   1120       // file needs relocation. It's in good shape as is.
   1121       return kNoDexOptNeeded;
   1122     }
   1123 
   1124     if (filter_okay && Status() == kOatRelocationOutOfDate) {
   1125       return kDex2OatForRelocation;
   1126     }
   1127 
   1128     if (IsUseable()) {
   1129       return kDex2OatForFilter;
   1130     }
   1131 
   1132     if (Status() == kOatBootImageOutOfDate) {
   1133       return kDex2OatForBootImage;
   1134     }
   1135   }
   1136 
   1137   if (oat_file_assistant_->HasOriginalDexFiles()) {
   1138     return kDex2OatFromScratch;
   1139   } else {
   1140     // Otherwise there is nothing we can do, even if we want to.
   1141     return kNoDexOptNeeded;
   1142   }
   1143 }
   1144 
   1145 const OatFile* OatFileAssistant::OatFileInfo::GetFile() {
   1146   CHECK(!file_released_) << "GetFile called after oat file released.";
   1147   if (!load_attempted_) {
   1148     load_attempted_ = true;
   1149     if (filename_provided_) {
   1150       bool executable = oat_file_assistant_->load_executable_;
   1151       if (executable && oat_file_assistant_->only_load_system_executable_) {
   1152         executable = LocationIsOnSystem(filename_.c_str());
   1153       }
   1154       std::string error_msg;
   1155       if (use_fd_) {
   1156         if (oat_fd_ >= 0 && vdex_fd_ >= 0) {
   1157           file_.reset(OatFile::Open(zip_fd_,
   1158                                     vdex_fd_,
   1159                                     oat_fd_,
   1160                                     filename_.c_str(),
   1161                                     nullptr,
   1162                                     nullptr,
   1163                                     executable,
   1164                                     false /* low_4gb */,
   1165                                     oat_file_assistant_->dex_location_.c_str(),
   1166                                     &error_msg));
   1167         }
   1168       } else {
   1169         file_.reset(OatFile::Open(/* zip_fd */ -1,
   1170                                   filename_.c_str(),
   1171                                   filename_.c_str(),
   1172                                   nullptr,
   1173                                   nullptr,
   1174                                   executable,
   1175                                   false /* low_4gb */,
   1176                                   oat_file_assistant_->dex_location_.c_str(),
   1177                                   &error_msg));
   1178       }
   1179       if (file_.get() == nullptr) {
   1180         VLOG(oat) << "OatFileAssistant test for existing oat file "
   1181           << filename_ << ": " << error_msg;
   1182       }
   1183     }
   1184   }
   1185   return file_.get();
   1186 }
   1187 
   1188 bool OatFileAssistant::OatFileInfo::CompilerFilterIsOkay(
   1189     CompilerFilter::Filter target, bool profile_changed, bool downgrade) {
   1190   const OatFile* file = GetFile();
   1191   if (file == nullptr) {
   1192     return false;
   1193   }
   1194 
   1195   CompilerFilter::Filter current = file->GetCompilerFilter();
   1196   if (profile_changed && CompilerFilter::DependsOnProfile(current)) {
   1197     VLOG(oat) << "Compiler filter not okay because Profile changed";
   1198     return false;
   1199   }
   1200   return downgrade ? !CompilerFilter::IsBetter(current, target) :
   1201     CompilerFilter::IsAsGoodAs(current, target);
   1202 }
   1203 
   1204 bool OatFileAssistant::OatFileInfo::ClassLoaderContextIsOkay(ClassLoaderContext* context) {
   1205   if (context == nullptr) {
   1206     VLOG(oat) << "ClassLoaderContext check ignored: null context";
   1207     return true;
   1208   }
   1209 
   1210   const OatFile* file = GetFile();
   1211   if (file == nullptr) {
   1212     // No oat file means we have nothing to verify.
   1213     return true;
   1214   }
   1215 
   1216   size_t dir_index = oat_file_assistant_->dex_location_.rfind('/');
   1217   std::string classpath_dir = (dir_index != std::string::npos)
   1218       ? oat_file_assistant_->dex_location_.substr(0, dir_index)
   1219       : "";
   1220 
   1221   if (!context->OpenDexFiles(oat_file_assistant_->isa_, classpath_dir)) {
   1222     VLOG(oat) << "ClassLoaderContext check failed: dex files from the context could not be opened";
   1223     return false;
   1224   }
   1225 
   1226   bool result = context->VerifyClassLoaderContextMatch(file->GetClassLoaderContext());
   1227   if (!result) {
   1228     VLOG(oat) << "ClassLoaderContext check failed. Context was "
   1229               << file->GetClassLoaderContext()
   1230               << ". The expected context is " << context->EncodeContextForOatFile(classpath_dir);
   1231   }
   1232   return result;
   1233 }
   1234 
   1235 bool OatFileAssistant::OatFileInfo::IsExecutable() {
   1236   const OatFile* file = GetFile();
   1237   return (file != nullptr && file->IsExecutable());
   1238 }
   1239 
   1240 void OatFileAssistant::OatFileInfo::Reset() {
   1241   load_attempted_ = false;
   1242   file_.reset();
   1243   status_attempted_ = false;
   1244 }
   1245 
   1246 void OatFileAssistant::OatFileInfo::Reset(const std::string& filename,
   1247                                           bool use_fd,
   1248                                           int zip_fd,
   1249                                           int vdex_fd,
   1250                                           int oat_fd) {
   1251   filename_provided_ = true;
   1252   filename_ = filename;
   1253   use_fd_ = use_fd;
   1254   zip_fd_ = zip_fd;
   1255   vdex_fd_ = vdex_fd;
   1256   oat_fd_ = oat_fd;
   1257   Reset();
   1258 }
   1259 
   1260 std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFile() {
   1261   file_released_ = true;
   1262   return std::move(file_);
   1263 }
   1264 
   1265 std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFileForUse() {
   1266   if (Status() == kOatUpToDate) {
   1267     return ReleaseFile();
   1268   }
   1269 
   1270   VLOG(oat) << "Oat File Assistant: No relocated oat file found,"
   1271     << " attempting to fall back to interpreting oat file instead.";
   1272 
   1273   if (Status() == kOatRelocationOutOfDate && !IsExecutable()) {
   1274     return ReleaseFile();
   1275   }
   1276 
   1277   switch (Status()) {
   1278     case kOatBootImageOutOfDate:
   1279       // OutOfDate may be either a mismatched image, or a missing image.
   1280       if (oat_file_assistant_->HasOriginalDexFiles()) {
   1281         // If there are original dex files, it is better to use them (to avoid a potential
   1282         // quickening mismatch because the boot image changed).
   1283         break;
   1284       }
   1285       // If we do not accept the oat file, we may not have access to dex bytecode at all. Grudgingly
   1286       // go forward.
   1287       FALLTHROUGH_INTENDED;
   1288 
   1289     case kOatRelocationOutOfDate:
   1290       // We are loading an oat file for runtime use that needs relocation.
   1291       // Reload the file non-executable to ensure that we interpret out of the
   1292       // dex code in the oat file rather than trying to execute the unrelocated
   1293       // compiled code.
   1294       oat_file_assistant_->load_executable_ = false;
   1295       Reset();
   1296       if (IsUseable()) {
   1297         CHECK(!IsExecutable());
   1298         return ReleaseFile();
   1299       }
   1300       break;
   1301 
   1302     case kOatUpToDate:
   1303     case kOatCannotOpen:
   1304     case kOatDexOutOfDate:
   1305       break;
   1306   }
   1307 
   1308   return std::unique_ptr<OatFile>();
   1309 }
   1310 
   1311 // TODO(calin): we could provide a more refined status here
   1312 // (e.g. run from uncompressed apk, run with vdex but not oat etc). It will allow us to
   1313 // track more experiments but adds extra complexity.
   1314 void OatFileAssistant::GetOptimizationStatus(
   1315     const std::string& filename,
   1316     InstructionSet isa,
   1317     std::string* out_compilation_filter,
   1318     std::string* out_compilation_reason) {
   1319   // It may not be possible to load an oat file executable (e.g., selinux restrictions). Load
   1320   // non-executable and check the status manually.
   1321   OatFileAssistant oat_file_assistant(filename.c_str(), isa, false /* load_executable */);
   1322   std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile();
   1323 
   1324   if (oat_file == nullptr) {
   1325     *out_compilation_filter = "run-from-apk";
   1326     *out_compilation_reason = "unknown";
   1327     return;
   1328   }
   1329 
   1330   OatStatus status = oat_file_assistant.GivenOatFileStatus(*oat_file);
   1331   const char* reason = oat_file->GetCompilationReason();
   1332   *out_compilation_reason = reason == nullptr ? "unknown" : reason;
   1333   switch (status) {
   1334     case OatStatus::kOatUpToDate:
   1335       *out_compilation_filter = CompilerFilter::NameOfFilter(oat_file->GetCompilerFilter());
   1336       return;
   1337 
   1338     case kOatCannotOpen:  // This should never happen, but be robust.
   1339       *out_compilation_filter = "error";
   1340       *out_compilation_reason = "error";
   1341       return;
   1342 
   1343     // kOatBootImageOutOfDate - The oat file is up to date with respect to the
   1344     // dex file, but is out of date with respect to the boot image.
   1345     case kOatBootImageOutOfDate:
   1346       FALLTHROUGH_INTENDED;
   1347     case kOatDexOutOfDate:
   1348       if (oat_file_assistant.HasOriginalDexFiles()) {
   1349         *out_compilation_filter = "run-from-apk-fallback";
   1350       } else {
   1351         *out_compilation_filter = "run-from-vdex-fallback";
   1352       }
   1353       return;
   1354 
   1355     case kOatRelocationOutOfDate:
   1356       // On relocation-out-of-date, we'd run the dex code.
   1357       *out_compilation_filter = "run-from-vdex-fallback";
   1358       return;
   1359   }
   1360   LOG(FATAL) << "Unreachable";
   1361   UNREACHABLE();
   1362 }
   1363 
   1364 }  // namespace art
   1365