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