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 #include "zlib.h" 23 24 #include "android-base/stringprintf.h" 25 #include "android-base/strings.h" 26 27 #include "base/file_utils.h" 28 #include "base/logging.h" // For VLOG. 29 #include "base/macros.h" 30 #include "base/os.h" 31 #include "base/stl_util.h" 32 #include "base/string_view_cpp20.h" 33 #include "base/utils.h" 34 #include "class_linker.h" 35 #include "class_loader_context.h" 36 #include "compiler_filter.h" 37 #include "dex/art_dex_file_loader.h" 38 #include "dex/dex_file_loader.h" 39 #include "exec_utils.h" 40 #include "gc/heap.h" 41 #include "gc/space/image_space.h" 42 #include "image.h" 43 #include "oat.h" 44 #include "runtime.h" 45 #include "scoped_thread_state_change-inl.h" 46 #include "vdex_file.h" 47 48 namespace art { 49 50 using android::base::StringPrintf; 51 52 static constexpr const char* kAnonymousDexPrefix = "Anonymous-DexFile@"; 53 static constexpr const char* kVdexExtension = ".vdex"; 54 55 std::ostream& operator << (std::ostream& stream, const OatFileAssistant::OatStatus status) { 56 switch (status) { 57 case OatFileAssistant::kOatCannotOpen: 58 stream << "kOatCannotOpen"; 59 break; 60 case OatFileAssistant::kOatDexOutOfDate: 61 stream << "kOatDexOutOfDate"; 62 break; 63 case OatFileAssistant::kOatBootImageOutOfDate: 64 stream << "kOatBootImageOutOfDate"; 65 break; 66 case OatFileAssistant::kOatUpToDate: 67 stream << "kOatUpToDate"; 68 break; 69 default: 70 UNREACHABLE(); 71 } 72 73 return stream; 74 } 75 76 OatFileAssistant::OatFileAssistant(const char* dex_location, 77 const InstructionSet isa, 78 bool load_executable, 79 bool only_load_system_executable) 80 : OatFileAssistant(dex_location, 81 isa, 82 load_executable, 83 only_load_system_executable, 84 /*vdex_fd=*/ -1, 85 /*oat_fd=*/ -1, 86 /*zip_fd=*/ -1) {} 87 88 89 OatFileAssistant::OatFileAssistant(const char* dex_location, 90 const InstructionSet isa, 91 bool load_executable, 92 bool only_load_system_executable, 93 int vdex_fd, 94 int oat_fd, 95 int zip_fd) 96 : isa_(isa), 97 load_executable_(load_executable), 98 only_load_system_executable_(only_load_system_executable), 99 odex_(this, /*is_oat_location=*/ false), 100 oat_(this, /*is_oat_location=*/ true), 101 zip_fd_(zip_fd) { 102 CHECK(dex_location != nullptr) << "OatFileAssistant: null dex location"; 103 104 if (zip_fd < 0) { 105 CHECK_LE(oat_fd, 0) << "zip_fd must be provided with valid oat_fd. zip_fd=" << zip_fd 106 << " oat_fd=" << oat_fd; 107 CHECK_LE(vdex_fd, 0) << "zip_fd must be provided with valid vdex_fd. zip_fd=" << zip_fd 108 << " vdex_fd=" << vdex_fd;; 109 } 110 111 dex_location_.assign(dex_location); 112 113 if (load_executable_ && isa != kRuntimeISA) { 114 LOG(WARNING) << "OatFileAssistant: Load executable specified, " 115 << "but isa is not kRuntimeISA. Will not attempt to load executable."; 116 load_executable_ = false; 117 } 118 119 // Get the odex filename. 120 std::string error_msg; 121 std::string odex_file_name; 122 if (DexLocationToOdexFilename(dex_location_, isa_, &odex_file_name, &error_msg)) { 123 odex_.Reset(odex_file_name, UseFdToReadFiles(), zip_fd, vdex_fd, oat_fd); 124 } else { 125 LOG(WARNING) << "Failed to determine odex file name: " << error_msg; 126 } 127 128 if (!UseFdToReadFiles()) { 129 // Get the oat filename. 130 std::string oat_file_name; 131 if (DexLocationToOatFilename(dex_location_, isa_, &oat_file_name, &error_msg)) { 132 oat_.Reset(oat_file_name, /*use_fd=*/ false); 133 } else { 134 LOG(WARNING) << "Failed to determine oat file name for dex location " 135 << dex_location_ << ": " << error_msg; 136 } 137 } 138 139 // Check if the dex directory is writable. 140 // This will be needed in most uses of OatFileAssistant and so it's OK to 141 // compute it eagerly. (the only use which will not make use of it is 142 // OatFileAssistant::GetStatusDump()) 143 size_t pos = dex_location_.rfind('/'); 144 if (pos == std::string::npos) { 145 LOG(WARNING) << "Failed to determine dex file parent directory: " << dex_location_; 146 } else if (!UseFdToReadFiles()) { 147 // We cannot test for parent access when using file descriptors. That's ok 148 // because in this case we will always pick the odex file anyway. 149 std::string parent = dex_location_.substr(0, pos); 150 if (access(parent.c_str(), W_OK) == 0) { 151 dex_parent_writable_ = true; 152 } else { 153 VLOG(oat) << "Dex parent of " << dex_location_ << " is not writable: " << strerror(errno); 154 } 155 } 156 } 157 158 OatFileAssistant::~OatFileAssistant() { 159 // Clean up the lock file. 160 if (flock_.get() != nullptr) { 161 unlink(flock_->GetPath().c_str()); 162 } 163 } 164 165 bool OatFileAssistant::UseFdToReadFiles() { 166 return zip_fd_ >= 0; 167 } 168 169 bool OatFileAssistant::IsInBootClassPath() { 170 // Note: We check the current boot class path, regardless of the ISA 171 // specified by the user. This is okay, because the boot class path should 172 // be the same for all ISAs. 173 // TODO: Can we verify the boot class path is the same for all ISAs? 174 Runtime* runtime = Runtime::Current(); 175 ClassLinker* class_linker = runtime->GetClassLinker(); 176 const auto& boot_class_path = class_linker->GetBootClassPath(); 177 for (size_t i = 0; i < boot_class_path.size(); i++) { 178 if (boot_class_path[i]->GetLocation() == dex_location_) { 179 VLOG(oat) << "Dex location " << dex_location_ << " is in boot class path"; 180 return true; 181 } 182 } 183 return false; 184 } 185 186 int OatFileAssistant::GetDexOptNeeded(CompilerFilter::Filter target, 187 bool profile_changed, 188 bool downgrade, 189 ClassLoaderContext* class_loader_context, 190 const std::vector<int>& context_fds) { 191 OatFileInfo& info = GetBestInfo(); 192 DexOptNeeded dexopt_needed = info.GetDexOptNeeded(target, 193 profile_changed, 194 downgrade, 195 class_loader_context, 196 context_fds); 197 if (info.IsOatLocation() || dexopt_needed == kDex2OatFromScratch) { 198 return dexopt_needed; 199 } 200 return -dexopt_needed; 201 } 202 203 bool OatFileAssistant::IsUpToDate() { 204 return GetBestInfo().Status() == kOatUpToDate; 205 } 206 207 std::unique_ptr<OatFile> OatFileAssistant::GetBestOatFile() { 208 return GetBestInfo().ReleaseFileForUse(); 209 } 210 211 std::string OatFileAssistant::GetStatusDump() { 212 std::ostringstream status; 213 bool oat_file_exists = false; 214 bool odex_file_exists = false; 215 if (oat_.Status() != kOatCannotOpen) { 216 // If we can open the file, Filename should not return null. 217 CHECK(oat_.Filename() != nullptr); 218 219 oat_file_exists = true; 220 status << *oat_.Filename() << "[status=" << oat_.Status() << ", "; 221 const OatFile* file = oat_.GetFile(); 222 if (file == nullptr) { 223 // If the file is null even though the status is not kOatCannotOpen, it 224 // means we must have a vdex file with no corresponding oat file. In 225 // this case we cannot determine the compilation filter. Indicate that 226 // we have only the vdex file instead. 227 status << "vdex-only"; 228 } else { 229 status << "compilation_filter=" << CompilerFilter::NameOfFilter(file->GetCompilerFilter()); 230 } 231 } 232 233 if (odex_.Status() != kOatCannotOpen) { 234 // If we can open the file, Filename should not return null. 235 CHECK(odex_.Filename() != nullptr); 236 237 odex_file_exists = true; 238 if (oat_file_exists) { 239 status << "] "; 240 } 241 status << *odex_.Filename() << "[status=" << odex_.Status() << ", "; 242 const OatFile* file = odex_.GetFile(); 243 if (file == nullptr) { 244 status << "vdex-only"; 245 } else { 246 status << "compilation_filter=" << CompilerFilter::NameOfFilter(file->GetCompilerFilter()); 247 } 248 } 249 250 if (!oat_file_exists && !odex_file_exists) { 251 status << "invalid["; 252 } 253 254 status << "]"; 255 return status.str(); 256 } 257 258 std::vector<std::unique_ptr<const DexFile>> OatFileAssistant::LoadDexFiles( 259 const OatFile &oat_file, const char *dex_location) { 260 std::vector<std::unique_ptr<const DexFile>> dex_files; 261 if (LoadDexFiles(oat_file, dex_location, &dex_files)) { 262 return dex_files; 263 } else { 264 return std::vector<std::unique_ptr<const DexFile>>(); 265 } 266 } 267 268 bool OatFileAssistant::LoadDexFiles( 269 const OatFile &oat_file, 270 const std::string& dex_location, 271 std::vector<std::unique_ptr<const DexFile>>* out_dex_files) { 272 // Load the main dex file. 273 std::string error_msg; 274 const OatDexFile* oat_dex_file = oat_file.GetOatDexFile( 275 dex_location.c_str(), nullptr, &error_msg); 276 if (oat_dex_file == nullptr) { 277 LOG(WARNING) << error_msg; 278 return false; 279 } 280 281 std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg); 282 if (dex_file.get() == nullptr) { 283 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg; 284 return false; 285 } 286 out_dex_files->push_back(std::move(dex_file)); 287 288 // Load the rest of the multidex entries 289 for (size_t i = 1;; i++) { 290 std::string multidex_dex_location = DexFileLoader::GetMultiDexLocation(i, dex_location.c_str()); 291 oat_dex_file = oat_file.GetOatDexFile(multidex_dex_location.c_str(), nullptr); 292 if (oat_dex_file == nullptr) { 293 // There are no more multidex entries to load. 294 break; 295 } 296 297 dex_file = oat_dex_file->OpenDexFile(&error_msg); 298 if (dex_file.get() == nullptr) { 299 LOG(WARNING) << "Failed to open dex file from oat dex file: " << error_msg; 300 return false; 301 } 302 out_dex_files->push_back(std::move(dex_file)); 303 } 304 return true; 305 } 306 307 bool OatFileAssistant::HasOriginalDexFiles() { 308 // Ensure GetRequiredDexChecksums has been run so that 309 // has_original_dex_files_ is initialized. We don't care about the result of 310 // GetRequiredDexChecksums. 311 GetRequiredDexChecksums(); 312 return has_original_dex_files_; 313 } 314 315 OatFileAssistant::OatStatus OatFileAssistant::OdexFileStatus() { 316 return odex_.Status(); 317 } 318 319 OatFileAssistant::OatStatus OatFileAssistant::OatFileStatus() { 320 return oat_.Status(); 321 } 322 323 bool OatFileAssistant::DexChecksumUpToDate(const VdexFile& file, std::string* error_msg) { 324 const std::vector<uint32_t>* required_dex_checksums = GetRequiredDexChecksums(); 325 if (required_dex_checksums == nullptr) { 326 LOG(WARNING) << "Required dex checksums not found. Assuming dex checksums are up to date."; 327 return true; 328 } 329 330 uint32_t number_of_dex_files = file.GetVerifierDepsHeader().GetNumberOfDexFiles(); 331 if (required_dex_checksums->size() != number_of_dex_files) { 332 *error_msg = StringPrintf("expected %zu dex files but found %u", 333 required_dex_checksums->size(), 334 number_of_dex_files); 335 return false; 336 } 337 338 for (uint32_t i = 0; i < number_of_dex_files; i++) { 339 uint32_t expected_checksum = (*required_dex_checksums)[i]; 340 uint32_t actual_checksum = file.GetLocationChecksum(i); 341 if (expected_checksum != actual_checksum) { 342 std::string dex = DexFileLoader::GetMultiDexLocation(i, dex_location_.c_str()); 343 *error_msg = StringPrintf("Dex checksum does not match for dex: %s." 344 "Expected: %u, actual: %u", 345 dex.c_str(), 346 expected_checksum, 347 actual_checksum); 348 return false; 349 } 350 } 351 352 return true; 353 } 354 355 bool OatFileAssistant::DexChecksumUpToDate(const OatFile& file, std::string* error_msg) { 356 const std::vector<uint32_t>* required_dex_checksums = GetRequiredDexChecksums(); 357 if (required_dex_checksums == nullptr) { 358 LOG(WARNING) << "Required dex checksums not found. Assuming dex checksums are up to date."; 359 return true; 360 } 361 362 uint32_t number_of_dex_files = file.GetOatHeader().GetDexFileCount(); 363 if (required_dex_checksums->size() != number_of_dex_files) { 364 *error_msg = StringPrintf("expected %zu dex files but found %u", 365 required_dex_checksums->size(), 366 number_of_dex_files); 367 return false; 368 } 369 370 for (uint32_t i = 0; i < number_of_dex_files; i++) { 371 std::string dex = DexFileLoader::GetMultiDexLocation(i, dex_location_.c_str()); 372 uint32_t expected_checksum = (*required_dex_checksums)[i]; 373 const OatDexFile* oat_dex_file = file.GetOatDexFile(dex.c_str(), nullptr); 374 if (oat_dex_file == nullptr) { 375 *error_msg = StringPrintf("failed to find %s in %s", dex.c_str(), file.GetLocation().c_str()); 376 return false; 377 } 378 uint32_t actual_checksum = oat_dex_file->GetDexFileLocationChecksum(); 379 if (expected_checksum != actual_checksum) { 380 VLOG(oat) << "Dex checksum does not match for dex: " << dex 381 << ". Expected: " << expected_checksum 382 << ", Actual: " << actual_checksum; 383 return false; 384 } 385 } 386 return true; 387 } 388 389 OatFileAssistant::OatStatus OatFileAssistant::GivenOatFileStatus(const OatFile& file) { 390 // Verify the ART_USE_READ_BARRIER state. 391 // TODO: Don't fully reject files due to read barrier state. If they contain 392 // compiled code and are otherwise okay, we should return something like 393 // kOatRelocationOutOfDate. If they don't contain compiled code, the read 394 // barrier state doesn't matter. 395 const bool is_cc = file.GetOatHeader().IsConcurrentCopying(); 396 constexpr bool kRuntimeIsCC = kUseReadBarrier; 397 if (is_cc != kRuntimeIsCC) { 398 return kOatCannotOpen; 399 } 400 401 // Verify the dex checksum. 402 std::string error_msg; 403 VdexFile* vdex = file.GetVdexFile(); 404 if (!DexChecksumUpToDate(*vdex, &error_msg)) { 405 LOG(ERROR) << error_msg; 406 return kOatDexOutOfDate; 407 } 408 409 CompilerFilter::Filter current_compiler_filter = file.GetCompilerFilter(); 410 411 // Verify the image checksum 412 if (CompilerFilter::DependsOnImageChecksum(current_compiler_filter)) { 413 if (!ValidateBootClassPathChecksums(file)) { 414 VLOG(oat) << "Oat image checksum does not match image checksum."; 415 return kOatBootImageOutOfDate; 416 } 417 } else { 418 VLOG(oat) << "Image checksum test skipped for compiler filter " << current_compiler_filter; 419 } 420 421 // zip_file_only_contains_uncompressed_dex_ is only set during fetching the dex checksums. 422 DCHECK(required_dex_checksums_attempted_); 423 if (only_load_system_executable_ && 424 !LocationIsOnSystem(file.GetLocation().c_str()) && 425 file.ContainsDexCode() && 426 zip_file_only_contains_uncompressed_dex_) { 427 LOG(ERROR) << "Not loading " 428 << dex_location_ 429 << ": oat file has dex code, but APK has uncompressed dex code"; 430 return kOatDexOutOfDate; 431 } 432 433 return kOatUpToDate; 434 } 435 436 bool OatFileAssistant::AnonymousDexVdexLocation(const std::vector<const DexFile::Header*>& headers, 437 InstructionSet isa, 438 /* out */ uint32_t* location_checksum, 439 /* out */ std::string* dex_location, 440 /* out */ std::string* vdex_filename) { 441 uint32_t checksum = adler32(0L, Z_NULL, 0); 442 for (const DexFile::Header* header : headers) { 443 checksum = adler32_combine(checksum, 444 header->checksum_, 445 header->file_size_ - DexFile::kNumNonChecksumBytes); 446 } 447 *location_checksum = checksum; 448 449 const std::string& data_dir = Runtime::Current()->GetProcessDataDirectory(); 450 if (data_dir.empty() || Runtime::Current()->IsZygote()) { 451 *dex_location = StringPrintf("%s%u", kAnonymousDexPrefix, checksum); 452 return false; 453 } 454 *dex_location = StringPrintf("%s/%s%u.jar", data_dir.c_str(), kAnonymousDexPrefix, checksum); 455 456 std::string odex_filename; 457 std::string error_msg; 458 if (!DexLocationToOdexFilename(*dex_location, isa, &odex_filename, &error_msg)) { 459 LOG(WARNING) << "Could not get odex filename for " << *dex_location << ": " << error_msg; 460 return false; 461 } 462 463 *vdex_filename = GetVdexFilename(odex_filename); 464 return true; 465 } 466 467 bool OatFileAssistant::IsAnonymousVdexBasename(const std::string& basename) { 468 DCHECK(basename.find('/') == std::string::npos); 469 // `basename` must have format: <kAnonymousDexPrefix><checksum><kVdexExtension> 470 if (basename.size() < strlen(kAnonymousDexPrefix) + strlen(kVdexExtension) + 1 || 471 !android::base::StartsWith(basename.c_str(), kAnonymousDexPrefix) || 472 !android::base::EndsWith(basename, kVdexExtension)) { 473 return false; 474 } 475 // Check that all characters between the prefix and extension are decimal digits. 476 for (size_t i = strlen(kAnonymousDexPrefix); i < basename.size() - strlen(kVdexExtension); ++i) { 477 if (!std::isdigit(basename[i])) { 478 return false; 479 } 480 } 481 return true; 482 } 483 484 static bool DexLocationToOdexNames(const std::string& location, 485 InstructionSet isa, 486 std::string* odex_filename, 487 std::string* oat_dir, 488 std::string* isa_dir, 489 std::string* error_msg) { 490 CHECK(odex_filename != nullptr); 491 CHECK(error_msg != nullptr); 492 493 // The odex file name is formed by replacing the dex_location extension with 494 // .odex and inserting an oat/<isa> directory. For example: 495 // location = /foo/bar/baz.jar 496 // odex_location = /foo/bar/oat/<isa>/baz.odex 497 498 // Find the directory portion of the dex location and add the oat/<isa> 499 // directory. 500 size_t pos = location.rfind('/'); 501 if (pos == std::string::npos) { 502 *error_msg = "Dex location " + location + " has no directory."; 503 return false; 504 } 505 std::string dir = location.substr(0, pos+1); 506 // Add the oat directory. 507 dir += "oat"; 508 if (oat_dir != nullptr) { 509 *oat_dir = dir; 510 } 511 // Add the isa directory 512 dir += "/" + std::string(GetInstructionSetString(isa)); 513 if (isa_dir != nullptr) { 514 *isa_dir = dir; 515 } 516 517 // Get the base part of the file without the extension. 518 std::string file = location.substr(pos+1); 519 pos = file.rfind('.'); 520 if (pos == std::string::npos) { 521 *error_msg = "Dex location " + location + " has no extension."; 522 return false; 523 } 524 std::string base = file.substr(0, pos); 525 526 *odex_filename = dir + "/" + base + ".odex"; 527 return true; 528 } 529 530 bool OatFileAssistant::DexLocationToOdexFilename(const std::string& location, 531 InstructionSet isa, 532 std::string* odex_filename, 533 std::string* error_msg) { 534 return DexLocationToOdexNames(location, isa, odex_filename, nullptr, nullptr, error_msg); 535 } 536 537 bool OatFileAssistant::DexLocationToOatFilename(const std::string& location, 538 InstructionSet isa, 539 std::string* oat_filename, 540 std::string* error_msg) { 541 CHECK(oat_filename != nullptr); 542 CHECK(error_msg != nullptr); 543 544 // If ANDROID_DATA is not set, return false instead of aborting. 545 // This can occur for preopt when using a class loader context. 546 if (GetAndroidDataSafe(error_msg).empty()) { 547 *error_msg = "GetAndroidDataSafe failed: " + *error_msg; 548 return false; 549 } 550 551 std::string cache_dir = GetDalvikCache(GetInstructionSetString(isa)); 552 if (cache_dir.empty()) { 553 *error_msg = "Dalvik cache directory does not exist"; 554 return false; 555 } 556 557 // TODO: The oat file assistant should be the definitive place for 558 // determining the oat file name from the dex location, not 559 // GetDalvikCacheFilename. 560 return GetDalvikCacheFilename(location.c_str(), cache_dir.c_str(), oat_filename, error_msg); 561 } 562 563 const std::vector<uint32_t>* OatFileAssistant::GetRequiredDexChecksums() { 564 if (!required_dex_checksums_attempted_) { 565 required_dex_checksums_attempted_ = true; 566 required_dex_checksums_found_ = false; 567 cached_required_dex_checksums_.clear(); 568 std::string error_msg; 569 const ArtDexFileLoader dex_file_loader; 570 if (dex_file_loader.GetMultiDexChecksums(dex_location_.c_str(), 571 &cached_required_dex_checksums_, 572 &error_msg, 573 zip_fd_, 574 &zip_file_only_contains_uncompressed_dex_)) { 575 required_dex_checksums_found_ = true; 576 has_original_dex_files_ = true; 577 } else { 578 // This can happen if the original dex file has been stripped from the 579 // apk. 580 VLOG(oat) << "OatFileAssistant: " << error_msg; 581 has_original_dex_files_ = false; 582 583 // Get the checksums from the odex if we can. 584 const OatFile* odex_file = odex_.GetFile(); 585 if (odex_file != nullptr) { 586 required_dex_checksums_found_ = true; 587 for (size_t i = 0; i < odex_file->GetOatHeader().GetDexFileCount(); i++) { 588 std::string dex = DexFileLoader::GetMultiDexLocation(i, dex_location_.c_str()); 589 const OatDexFile* odex_dex_file = odex_file->GetOatDexFile(dex.c_str(), nullptr); 590 if (odex_dex_file == nullptr) { 591 required_dex_checksums_found_ = false; 592 break; 593 } 594 cached_required_dex_checksums_.push_back(odex_dex_file->GetDexFileLocationChecksum()); 595 } 596 } 597 } 598 } 599 return required_dex_checksums_found_ ? &cached_required_dex_checksums_ : nullptr; 600 } 601 602 bool OatFileAssistant::ValidateBootClassPathChecksums(const OatFile& oat_file) { 603 // Get the BCP from the oat file. 604 const char* oat_boot_class_path = 605 oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathKey); 606 if (oat_boot_class_path == nullptr) { 607 return false; 608 } 609 610 // Check that the oat BCP is a prefix of current BCP locations and count components. 611 Runtime* runtime = Runtime::Current(); 612 size_t component_count = 0u; 613 std::string_view remaining_bcp(oat_boot_class_path); 614 bool bcp_ok = false; 615 for (const std::string& location : runtime->GetBootClassPathLocations()) { 616 if (!StartsWith(remaining_bcp, location)) { 617 break; 618 } 619 remaining_bcp.remove_prefix(location.size()); 620 ++component_count; 621 if (remaining_bcp.empty()) { 622 bcp_ok = true; 623 break; 624 } 625 if (!StartsWith(remaining_bcp, ":")) { 626 break; 627 } 628 remaining_bcp.remove_prefix(1u); 629 } 630 if (!bcp_ok) { 631 return false; 632 } 633 634 // Get the checksums. 635 const char* oat_boot_class_path_checksums = 636 oat_file.GetOatHeader().GetStoreValueByKey(OatHeader::kBootClassPathChecksumsKey); 637 if (oat_boot_class_path_checksums == nullptr) { 638 return false; 639 } 640 641 // Retrieve checksums for this portion of the BCP if we do not have them cached. 642 if (cached_boot_class_path_checksum_component_count_ != component_count) { 643 ArrayRef<const std::string> boot_class_path(runtime->GetBootClassPath()); 644 std::string error_msg; 645 std::string boot_class_path_checksums = gc::space::ImageSpace::GetBootClassPathChecksums( 646 boot_class_path.SubArray(/* pos= */ 0u, component_count), 647 runtime->GetImageLocation(), 648 isa_, 649 runtime->GetImageSpaceLoadingOrder(), 650 &error_msg); 651 if (boot_class_path_checksums.empty()) { 652 VLOG(oat) << "No image for oat image checksum to match against."; 653 654 if (HasOriginalDexFiles()) { 655 return false; 656 } 657 658 // If there is no original dex file to fall back to, grudgingly accept 659 // the oat file. This could technically lead to crashes, but there's no 660 // way we could find a better oat file to use for this dex location, 661 // and it's better than being stuck in a boot loop with no way out. 662 // The problem will hopefully resolve itself the next time the runtime 663 // starts up. 664 LOG(WARNING) << "Dex location " << dex_location_ << " does not seem to include dex file. " 665 << "Allow oat file use. This is potentially dangerous."; 666 667 return true; 668 } 669 cached_boot_class_path_checksum_component_count_ = component_count; 670 cached_boot_class_path_checksums_ = boot_class_path_checksums; 671 } 672 673 // Compare the checksums. 674 return cached_boot_class_path_checksums_ == oat_boot_class_path_checksums; 675 } 676 677 OatFileAssistant::OatFileInfo& OatFileAssistant::GetBestInfo() { 678 // TODO(calin): Document the side effects of class loading when 679 // running dalvikvm command line. 680 if (dex_parent_writable_ || UseFdToReadFiles()) { 681 // If the parent of the dex file is writable it means that we can 682 // create the odex file. In this case we unconditionally pick the odex 683 // as the best oat file. This corresponds to the regular use case when 684 // apps gets installed or when they load private, secondary dex file. 685 // For apps on the system partition the odex location will not be 686 // writable and thus the oat location might be more up to date. 687 return odex_; 688 } 689 690 // We cannot write to the odex location. This must be a system app. 691 692 // If the oat location is usable take it. 693 if (oat_.IsUseable()) { 694 return oat_; 695 } 696 697 // The oat file is not usable but the odex file might be up to date. 698 // This is an indication that we are dealing with an up to date prebuilt 699 // (that doesn't need relocation). 700 if (odex_.Status() == kOatUpToDate) { 701 return odex_; 702 } 703 704 // The oat file is not usable and the odex file is not up to date. 705 // However we have access to the original dex file which means we can make 706 // the oat location up to date. 707 if (HasOriginalDexFiles()) { 708 return oat_; 709 } 710 711 // We got into the worst situation here: 712 // - the oat location is not usable 713 // - the prebuild odex location is not up to date 714 // - and we don't have the original dex file anymore (stripped). 715 // Pick the odex if it exists, or the oat if not. 716 return (odex_.Status() == kOatCannotOpen) ? oat_ : odex_; 717 } 718 719 std::unique_ptr<gc::space::ImageSpace> OatFileAssistant::OpenImageSpace(const OatFile* oat_file) { 720 DCHECK(oat_file != nullptr); 721 std::string art_file = ReplaceFileExtension(oat_file->GetLocation(), "art"); 722 if (art_file.empty()) { 723 return nullptr; 724 } 725 std::string error_msg; 726 ScopedObjectAccess soa(Thread::Current()); 727 std::unique_ptr<gc::space::ImageSpace> ret = 728 gc::space::ImageSpace::CreateFromAppImage(art_file.c_str(), oat_file, &error_msg); 729 if (ret == nullptr && (VLOG_IS_ON(image) || OS::FileExists(art_file.c_str()))) { 730 LOG(INFO) << "Failed to open app image " << art_file.c_str() << " " << error_msg; 731 } 732 return ret; 733 } 734 735 OatFileAssistant::OatFileInfo::OatFileInfo(OatFileAssistant* oat_file_assistant, 736 bool is_oat_location) 737 : oat_file_assistant_(oat_file_assistant), is_oat_location_(is_oat_location) 738 {} 739 740 bool OatFileAssistant::OatFileInfo::IsOatLocation() { 741 return is_oat_location_; 742 } 743 744 const std::string* OatFileAssistant::OatFileInfo::Filename() { 745 return filename_provided_ ? &filename_ : nullptr; 746 } 747 748 bool OatFileAssistant::OatFileInfo::IsUseable() { 749 switch (Status()) { 750 case kOatCannotOpen: 751 case kOatDexOutOfDate: 752 case kOatBootImageOutOfDate: return false; 753 754 case kOatUpToDate: return true; 755 } 756 UNREACHABLE(); 757 } 758 759 OatFileAssistant::OatStatus OatFileAssistant::OatFileInfo::Status() { 760 if (!status_attempted_) { 761 status_attempted_ = true; 762 const OatFile* file = GetFile(); 763 if (file == nullptr) { 764 // Check to see if there is a vdex file we can make use of. 765 std::string error_msg; 766 std::string vdex_filename = GetVdexFilename(filename_); 767 std::unique_ptr<VdexFile> vdex; 768 if (use_fd_) { 769 if (vdex_fd_ >= 0) { 770 struct stat s; 771 int rc = TEMP_FAILURE_RETRY(fstat(vdex_fd_, &s)); 772 if (rc == -1) { 773 error_msg = StringPrintf("Failed getting length of the vdex file %s.", strerror(errno)); 774 } else { 775 vdex = VdexFile::Open(vdex_fd_, 776 s.st_size, 777 vdex_filename, 778 /*writable=*/ false, 779 /*low_4gb=*/ false, 780 /*unquicken=*/ false, 781 &error_msg); 782 } 783 } 784 } else { 785 vdex = VdexFile::Open(vdex_filename, 786 /*writable=*/ false, 787 /*low_4gb=*/ false, 788 /*unquicken=*/ false, 789 &error_msg); 790 } 791 if (vdex == nullptr) { 792 status_ = kOatCannotOpen; 793 VLOG(oat) << "unable to open vdex file " << vdex_filename << ": " << error_msg; 794 } else { 795 if (oat_file_assistant_->DexChecksumUpToDate(*vdex, &error_msg)) { 796 // The vdex file does not contain enough information to determine 797 // whether it is up to date with respect to the boot image, so we 798 // assume it is out of date. 799 VLOG(oat) << error_msg; 800 status_ = kOatBootImageOutOfDate; 801 } else { 802 status_ = kOatDexOutOfDate; 803 } 804 } 805 } else { 806 status_ = oat_file_assistant_->GivenOatFileStatus(*file); 807 VLOG(oat) << file->GetLocation() << " is " << status_ 808 << " with filter " << file->GetCompilerFilter(); 809 } 810 } 811 return status_; 812 } 813 814 OatFileAssistant::DexOptNeeded OatFileAssistant::OatFileInfo::GetDexOptNeeded( 815 CompilerFilter::Filter target, 816 bool profile_changed, 817 bool downgrade, 818 ClassLoaderContext* context, 819 const std::vector<int>& context_fds) { 820 821 bool filter_okay = CompilerFilterIsOkay(target, profile_changed, downgrade); 822 bool class_loader_context_okay = ClassLoaderContextIsOkay(context, context_fds); 823 824 // Only check the filter and relocation if the class loader context is ok. 825 // If it is not, we will return kDex2OatFromScratch as the compilation needs to be redone. 826 if (class_loader_context_okay) { 827 if (filter_okay && Status() == kOatUpToDate) { 828 // The oat file is in good shape as is. 829 return kNoDexOptNeeded; 830 } 831 832 if (IsUseable()) { 833 return kDex2OatForFilter; 834 } 835 836 if (Status() == kOatBootImageOutOfDate) { 837 return kDex2OatForBootImage; 838 } 839 } 840 841 if (oat_file_assistant_->HasOriginalDexFiles()) { 842 return kDex2OatFromScratch; 843 } else { 844 // Otherwise there is nothing we can do, even if we want to. 845 return kNoDexOptNeeded; 846 } 847 } 848 849 const OatFile* OatFileAssistant::OatFileInfo::GetFile() { 850 CHECK(!file_released_) << "GetFile called after oat file released."; 851 if (!load_attempted_) { 852 load_attempted_ = true; 853 if (filename_provided_) { 854 bool executable = oat_file_assistant_->load_executable_; 855 if (executable && oat_file_assistant_->only_load_system_executable_) { 856 executable = LocationIsOnSystem(filename_.c_str()); 857 } 858 VLOG(oat) << "Loading " << filename_ << " with executable: " << executable; 859 std::string error_msg; 860 if (use_fd_) { 861 if (oat_fd_ >= 0 && vdex_fd_ >= 0) { 862 file_.reset(OatFile::Open(zip_fd_, 863 vdex_fd_, 864 oat_fd_, 865 filename_.c_str(), 866 executable, 867 /*low_4gb=*/ false, 868 oat_file_assistant_->dex_location_.c_str(), 869 /*reservation=*/ nullptr, 870 &error_msg)); 871 } 872 } else { 873 file_.reset(OatFile::Open(/*zip_fd=*/ -1, 874 filename_.c_str(), 875 filename_.c_str(), 876 executable, 877 /*low_4gb=*/ false, 878 oat_file_assistant_->dex_location_.c_str(), 879 /*reservation=*/ nullptr, 880 &error_msg)); 881 } 882 if (file_.get() == nullptr) { 883 VLOG(oat) << "OatFileAssistant test for existing oat file " 884 << filename_ << ": " << error_msg; 885 } else { 886 VLOG(oat) << "Successfully loaded " << filename_ << " with executable: " << executable; 887 } 888 } 889 } 890 return file_.get(); 891 } 892 893 bool OatFileAssistant::OatFileInfo::CompilerFilterIsOkay( 894 CompilerFilter::Filter target, bool profile_changed, bool downgrade) { 895 const OatFile* file = GetFile(); 896 if (file == nullptr) { 897 return false; 898 } 899 900 CompilerFilter::Filter current = file->GetCompilerFilter(); 901 if (profile_changed && CompilerFilter::DependsOnProfile(current)) { 902 VLOG(oat) << "Compiler filter not okay because Profile changed"; 903 return false; 904 } 905 return downgrade ? !CompilerFilter::IsBetter(current, target) : 906 CompilerFilter::IsAsGoodAs(current, target); 907 } 908 909 bool OatFileAssistant::OatFileInfo::ClassLoaderContextIsOkay(ClassLoaderContext* context, 910 const std::vector<int>& context_fds) { 911 if (context == nullptr) { 912 VLOG(oat) << "ClassLoaderContext check ignored: null context"; 913 return true; 914 } 915 916 const OatFile* file = GetFile(); 917 if (file == nullptr) { 918 // No oat file means we have nothing to verify. 919 return true; 920 } 921 922 size_t dir_index = oat_file_assistant_->dex_location_.rfind('/'); 923 std::string classpath_dir = (dir_index != std::string::npos) 924 ? oat_file_assistant_->dex_location_.substr(0, dir_index) 925 : ""; 926 927 if (!context->OpenDexFiles(oat_file_assistant_->isa_, classpath_dir, context_fds)) { 928 VLOG(oat) << "ClassLoaderContext check failed: dex files from the context could not be opened"; 929 return false; 930 } 931 932 const bool result = context->VerifyClassLoaderContextMatch(file->GetClassLoaderContext()) != 933 ClassLoaderContext::VerificationResult::kMismatch; 934 if (!result) { 935 VLOG(oat) << "ClassLoaderContext check failed. Context was " 936 << file->GetClassLoaderContext() 937 << ". The expected context is " << context->EncodeContextForOatFile(classpath_dir); 938 } 939 return result; 940 } 941 942 bool OatFileAssistant::OatFileInfo::IsExecutable() { 943 const OatFile* file = GetFile(); 944 return (file != nullptr && file->IsExecutable()); 945 } 946 947 void OatFileAssistant::OatFileInfo::Reset() { 948 load_attempted_ = false; 949 file_.reset(); 950 status_attempted_ = false; 951 } 952 953 void OatFileAssistant::OatFileInfo::Reset(const std::string& filename, 954 bool use_fd, 955 int zip_fd, 956 int vdex_fd, 957 int oat_fd) { 958 filename_provided_ = true; 959 filename_ = filename; 960 use_fd_ = use_fd; 961 zip_fd_ = zip_fd; 962 vdex_fd_ = vdex_fd; 963 oat_fd_ = oat_fd; 964 Reset(); 965 } 966 967 std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFile() { 968 file_released_ = true; 969 return std::move(file_); 970 } 971 972 std::unique_ptr<OatFile> OatFileAssistant::OatFileInfo::ReleaseFileForUse() { 973 if (Status() == kOatUpToDate) { 974 return ReleaseFile(); 975 } 976 977 VLOG(oat) << "Oat File Assistant: No relocated oat file found," 978 << " attempting to fall back to interpreting oat file instead."; 979 980 switch (Status()) { 981 case kOatBootImageOutOfDate: 982 // OutOfDate may be either a mismatched image, or a missing image. 983 if (oat_file_assistant_->HasOriginalDexFiles()) { 984 // If there are original dex files, it is better to use them (to avoid a potential 985 // quickening mismatch because the boot image changed). 986 break; 987 } 988 // If we do not accept the oat file, we may not have access to dex bytecode at all. Grudgingly 989 // go forward. 990 FALLTHROUGH_INTENDED; 991 992 case kOatUpToDate: 993 case kOatCannotOpen: 994 case kOatDexOutOfDate: 995 break; 996 } 997 998 return std::unique_ptr<OatFile>(); 999 } 1000 1001 // TODO(calin): we could provide a more refined status here 1002 // (e.g. run from uncompressed apk, run with vdex but not oat etc). It will allow us to 1003 // track more experiments but adds extra complexity. 1004 void OatFileAssistant::GetOptimizationStatus( 1005 const std::string& filename, 1006 InstructionSet isa, 1007 std::string* out_compilation_filter, 1008 std::string* out_compilation_reason) { 1009 // It may not be possible to load an oat file executable (e.g., selinux restrictions). Load 1010 // non-executable and check the status manually. 1011 OatFileAssistant oat_file_assistant(filename.c_str(), isa, /*load_executable=*/ false); 1012 std::unique_ptr<OatFile> oat_file = oat_file_assistant.GetBestOatFile(); 1013 1014 if (oat_file == nullptr) { 1015 *out_compilation_filter = "run-from-apk"; 1016 *out_compilation_reason = "unknown"; 1017 return; 1018 } 1019 1020 OatStatus status = oat_file_assistant.GivenOatFileStatus(*oat_file); 1021 const char* reason = oat_file->GetCompilationReason(); 1022 *out_compilation_reason = reason == nullptr ? "unknown" : reason; 1023 switch (status) { 1024 case OatStatus::kOatUpToDate: 1025 *out_compilation_filter = CompilerFilter::NameOfFilter(oat_file->GetCompilerFilter()); 1026 return; 1027 1028 case kOatCannotOpen: // This should never happen, but be robust. 1029 *out_compilation_filter = "error"; 1030 *out_compilation_reason = "error"; 1031 return; 1032 1033 // kOatBootImageOutOfDate - The oat file is up to date with respect to the 1034 // dex file, but is out of date with respect to the boot image. 1035 case kOatBootImageOutOfDate: 1036 FALLTHROUGH_INTENDED; 1037 case kOatDexOutOfDate: 1038 if (oat_file_assistant.HasOriginalDexFiles()) { 1039 *out_compilation_filter = "run-from-apk-fallback"; 1040 } else { 1041 *out_compilation_filter = "run-from-vdex-fallback"; 1042 } 1043 return; 1044 } 1045 LOG(FATAL) << "Unreachable"; 1046 UNREACHABLE(); 1047 } 1048 1049 } // namespace art 1050