image_space.cc revision 288b1e9a0dddfb91e85067fe81de55174f313c7c
1/* 2 * Copyright (C) 2011 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 "image_space.h" 18 19#include <dirent.h> 20#include <lz4.h> 21#include <random> 22#include <sys/statvfs.h> 23#include <sys/types.h> 24#include <unistd.h> 25 26#include "art_method.h" 27#include "base/macros.h" 28#include "base/stl_util.h" 29#include "base/scoped_flock.h" 30#include "base/time_utils.h" 31#include "base/unix_file/fd_file.h" 32#include "gc/accounting/space_bitmap-inl.h" 33#include "mirror/class-inl.h" 34#include "mirror/object-inl.h" 35#include "oat_file.h" 36#include "os.h" 37#include "space-inl.h" 38#include "utils.h" 39 40namespace art { 41namespace gc { 42namespace space { 43 44Atomic<uint32_t> ImageSpace::bitmap_index_(0); 45 46ImageSpace::ImageSpace(const std::string& image_filename, 47 const char* image_location, 48 MemMap* mem_map, 49 accounting::ContinuousSpaceBitmap* live_bitmap, 50 uint8_t* end, 51 MemMap* shadow_map) 52 : MemMapSpace(image_filename, mem_map, mem_map->Begin(), end, end, 53 kGcRetentionPolicyNeverCollect), 54 oat_file_non_owned_(nullptr), 55 image_location_(image_location), 56 shadow_map_(shadow_map) { 57 DCHECK(live_bitmap != nullptr); 58 live_bitmap_.reset(live_bitmap); 59} 60 61static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) { 62 CHECK_ALIGNED(min_delta, kPageSize); 63 CHECK_ALIGNED(max_delta, kPageSize); 64 CHECK_LT(min_delta, max_delta); 65 66 int32_t r = GetRandomNumber<int32_t>(min_delta, max_delta); 67 if (r % 2 == 0) { 68 r = RoundUp(r, kPageSize); 69 } else { 70 r = RoundDown(r, kPageSize); 71 } 72 CHECK_LE(min_delta, r); 73 CHECK_GE(max_delta, r); 74 CHECK_ALIGNED(r, kPageSize); 75 return r; 76} 77 78// We are relocating or generating the core image. We should get rid of everything. It is all 79// out-of-date. We also don't really care if this fails since it is just a convenience. 80// Adapted from prune_dex_cache(const char* subdir) in frameworks/native/cmds/installd/commands.c 81// Note this should only be used during first boot. 82static void RealPruneDalvikCache(const std::string& cache_dir_path); 83 84static void PruneDalvikCache(InstructionSet isa) { 85 CHECK_NE(isa, kNone); 86 // Prune the base /data/dalvik-cache. 87 RealPruneDalvikCache(GetDalvikCacheOrDie(".", false)); 88 // Prune /data/dalvik-cache/<isa>. 89 RealPruneDalvikCache(GetDalvikCacheOrDie(GetInstructionSetString(isa), false)); 90} 91 92static void RealPruneDalvikCache(const std::string& cache_dir_path) { 93 if (!OS::DirectoryExists(cache_dir_path.c_str())) { 94 return; 95 } 96 DIR* cache_dir = opendir(cache_dir_path.c_str()); 97 if (cache_dir == nullptr) { 98 PLOG(WARNING) << "Unable to open " << cache_dir_path << " to delete it's contents"; 99 return; 100 } 101 102 for (struct dirent* de = readdir(cache_dir); de != nullptr; de = readdir(cache_dir)) { 103 const char* name = de->d_name; 104 if (strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { 105 continue; 106 } 107 // We only want to delete regular files and symbolic links. 108 if (de->d_type != DT_REG && de->d_type != DT_LNK) { 109 if (de->d_type != DT_DIR) { 110 // We do expect some directories (namely the <isa> for pruning the base dalvik-cache). 111 LOG(WARNING) << "Unexpected file type of " << std::hex << de->d_type << " encountered."; 112 } 113 continue; 114 } 115 std::string cache_file(cache_dir_path); 116 cache_file += '/'; 117 cache_file += name; 118 if (TEMP_FAILURE_RETRY(unlink(cache_file.c_str())) != 0) { 119 PLOG(ERROR) << "Unable to unlink " << cache_file; 120 continue; 121 } 122 } 123 CHECK_EQ(0, TEMP_FAILURE_RETRY(closedir(cache_dir))) << "Unable to close directory."; 124} 125 126// We write out an empty file to the zygote's ISA specific cache dir at the start of 127// every zygote boot and delete it when the boot completes. If we find a file already 128// present, it usually means the boot didn't complete. We wipe the entire dalvik 129// cache if that's the case. 130static void MarkZygoteStart(const InstructionSet isa, const uint32_t max_failed_boots) { 131 const std::string isa_subdir = GetDalvikCacheOrDie(GetInstructionSetString(isa), false); 132 const std::string boot_marker = isa_subdir + "/.booting"; 133 const char* file_name = boot_marker.c_str(); 134 135 uint32_t num_failed_boots = 0; 136 std::unique_ptr<File> file(OS::OpenFileReadWrite(file_name)); 137 if (file.get() == nullptr) { 138 file.reset(OS::CreateEmptyFile(file_name)); 139 140 if (file.get() == nullptr) { 141 PLOG(WARNING) << "Failed to create boot marker."; 142 return; 143 } 144 } else { 145 if (!file->ReadFully(&num_failed_boots, sizeof(num_failed_boots))) { 146 PLOG(WARNING) << "Failed to read boot marker."; 147 file->Erase(); 148 return; 149 } 150 } 151 152 if (max_failed_boots != 0 && num_failed_boots > max_failed_boots) { 153 LOG(WARNING) << "Incomplete boot detected. Pruning dalvik cache"; 154 RealPruneDalvikCache(isa_subdir); 155 } 156 157 ++num_failed_boots; 158 VLOG(startup) << "Number of failed boots on : " << boot_marker << " = " << num_failed_boots; 159 160 if (lseek(file->Fd(), 0, SEEK_SET) == -1) { 161 PLOG(WARNING) << "Failed to write boot marker."; 162 file->Erase(); 163 return; 164 } 165 166 if (!file->WriteFully(&num_failed_boots, sizeof(num_failed_boots))) { 167 PLOG(WARNING) << "Failed to write boot marker."; 168 file->Erase(); 169 return; 170 } 171 172 if (file->FlushCloseOrErase() != 0) { 173 PLOG(WARNING) << "Failed to flush boot marker."; 174 } 175} 176 177static bool GenerateImage(const std::string& image_filename, InstructionSet image_isa, 178 std::string* error_msg) { 179 const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString()); 180 std::vector<std::string> boot_class_path; 181 Split(boot_class_path_string, ':', &boot_class_path); 182 if (boot_class_path.empty()) { 183 *error_msg = "Failed to generate image because no boot class path specified"; 184 return false; 185 } 186 // We should clean up so we are more likely to have room for the image. 187 if (Runtime::Current()->IsZygote()) { 188 LOG(INFO) << "Pruning dalvik-cache since we are generating an image and will need to recompile"; 189 PruneDalvikCache(image_isa); 190 } 191 192 std::vector<std::string> arg_vector; 193 194 std::string dex2oat(Runtime::Current()->GetCompilerExecutable()); 195 arg_vector.push_back(dex2oat); 196 197 std::string image_option_string("--image="); 198 image_option_string += image_filename; 199 arg_vector.push_back(image_option_string); 200 201 for (size_t i = 0; i < boot_class_path.size(); i++) { 202 arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]); 203 } 204 205 std::string oat_file_option_string("--oat-file="); 206 oat_file_option_string += ImageHeader::GetOatLocationFromImageLocation(image_filename); 207 arg_vector.push_back(oat_file_option_string); 208 209 // Note: we do not generate a fully debuggable boot image so we do not pass the 210 // compiler flag --debuggable here. 211 212 Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector); 213 CHECK_EQ(image_isa, kRuntimeISA) 214 << "We should always be generating an image for the current isa."; 215 216 int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, 217 ART_BASE_ADDRESS_MAX_DELTA); 218 LOG(INFO) << "Using an offset of 0x" << std::hex << base_offset << " from default " 219 << "art base address of 0x" << std::hex << ART_BASE_ADDRESS; 220 arg_vector.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset)); 221 222 if (!kIsTargetBuild) { 223 arg_vector.push_back("--host"); 224 } 225 226 const std::vector<std::string>& compiler_options = Runtime::Current()->GetImageCompilerOptions(); 227 for (size_t i = 0; i < compiler_options.size(); ++i) { 228 arg_vector.push_back(compiler_options[i].c_str()); 229 } 230 231 std::string command_line(Join(arg_vector, ' ')); 232 LOG(INFO) << "GenerateImage: " << command_line; 233 return Exec(arg_vector, error_msg); 234} 235 236bool ImageSpace::FindImageFilename(const char* image_location, 237 const InstructionSet image_isa, 238 std::string* system_filename, 239 bool* has_system, 240 std::string* cache_filename, 241 bool* dalvik_cache_exists, 242 bool* has_cache, 243 bool* is_global_cache) { 244 *has_system = false; 245 *has_cache = false; 246 // image_location = /system/framework/boot.art 247 // system_image_location = /system/framework/<image_isa>/boot.art 248 std::string system_image_filename(GetSystemImageFilename(image_location, image_isa)); 249 if (OS::FileExists(system_image_filename.c_str())) { 250 *system_filename = system_image_filename; 251 *has_system = true; 252 } 253 254 bool have_android_data = false; 255 *dalvik_cache_exists = false; 256 std::string dalvik_cache; 257 GetDalvikCache(GetInstructionSetString(image_isa), true, &dalvik_cache, 258 &have_android_data, dalvik_cache_exists, is_global_cache); 259 260 if (have_android_data && *dalvik_cache_exists) { 261 // Always set output location even if it does not exist, 262 // so that the caller knows where to create the image. 263 // 264 // image_location = /system/framework/boot.art 265 // *image_filename = /data/dalvik-cache/<image_isa>/boot.art 266 std::string error_msg; 267 if (!GetDalvikCacheFilename(image_location, dalvik_cache.c_str(), cache_filename, &error_msg)) { 268 LOG(WARNING) << error_msg; 269 return *has_system; 270 } 271 *has_cache = OS::FileExists(cache_filename->c_str()); 272 } 273 return *has_system || *has_cache; 274} 275 276static bool ReadSpecificImageHeader(const char* filename, ImageHeader* image_header) { 277 std::unique_ptr<File> image_file(OS::OpenFileForReading(filename)); 278 if (image_file.get() == nullptr) { 279 return false; 280 } 281 const bool success = image_file->ReadFully(image_header, sizeof(ImageHeader)); 282 if (!success || !image_header->IsValid()) { 283 return false; 284 } 285 return true; 286} 287 288// Relocate the image at image_location to dest_filename and relocate it by a random amount. 289static bool RelocateImage(const char* image_location, const char* dest_filename, 290 InstructionSet isa, std::string* error_msg) { 291 // We should clean up so we are more likely to have room for the image. 292 if (Runtime::Current()->IsZygote()) { 293 LOG(INFO) << "Pruning dalvik-cache since we are relocating an image and will need to recompile"; 294 PruneDalvikCache(isa); 295 } 296 297 std::string patchoat(Runtime::Current()->GetPatchoatExecutable()); 298 299 std::string input_image_location_arg("--input-image-location="); 300 input_image_location_arg += image_location; 301 302 std::string output_image_filename_arg("--output-image-file="); 303 output_image_filename_arg += dest_filename; 304 305 std::string input_oat_location_arg("--input-oat-location="); 306 input_oat_location_arg += ImageHeader::GetOatLocationFromImageLocation(image_location); 307 308 std::string output_oat_filename_arg("--output-oat-file="); 309 output_oat_filename_arg += ImageHeader::GetOatLocationFromImageLocation(dest_filename); 310 311 std::string instruction_set_arg("--instruction-set="); 312 instruction_set_arg += GetInstructionSetString(isa); 313 314 std::string base_offset_arg("--base-offset-delta="); 315 StringAppendF(&base_offset_arg, "%d", ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, 316 ART_BASE_ADDRESS_MAX_DELTA)); 317 318 std::vector<std::string> argv; 319 argv.push_back(patchoat); 320 321 argv.push_back(input_image_location_arg); 322 argv.push_back(output_image_filename_arg); 323 324 argv.push_back(input_oat_location_arg); 325 argv.push_back(output_oat_filename_arg); 326 327 argv.push_back(instruction_set_arg); 328 argv.push_back(base_offset_arg); 329 330 std::string command_line(Join(argv, ' ')); 331 LOG(INFO) << "RelocateImage: " << command_line; 332 return Exec(argv, error_msg); 333} 334 335static ImageHeader* ReadSpecificImageHeader(const char* filename, std::string* error_msg) { 336 std::unique_ptr<ImageHeader> hdr(new ImageHeader); 337 if (!ReadSpecificImageHeader(filename, hdr.get())) { 338 *error_msg = StringPrintf("Unable to read image header for %s", filename); 339 return nullptr; 340 } 341 return hdr.release(); 342} 343 344ImageHeader* ImageSpace::ReadImageHeaderOrDie(const char* image_location, 345 const InstructionSet image_isa) { 346 std::string error_msg; 347 ImageHeader* image_header = ReadImageHeader(image_location, image_isa, &error_msg); 348 if (image_header == nullptr) { 349 LOG(FATAL) << error_msg; 350 } 351 return image_header; 352} 353 354ImageHeader* ImageSpace::ReadImageHeader(const char* image_location, 355 const InstructionSet image_isa, 356 std::string* error_msg) { 357 std::string system_filename; 358 bool has_system = false; 359 std::string cache_filename; 360 bool has_cache = false; 361 bool dalvik_cache_exists = false; 362 bool is_global_cache = false; 363 if (FindImageFilename(image_location, image_isa, &system_filename, &has_system, 364 &cache_filename, &dalvik_cache_exists, &has_cache, &is_global_cache)) { 365 if (Runtime::Current()->ShouldRelocate()) { 366 if (has_system && has_cache) { 367 std::unique_ptr<ImageHeader> sys_hdr(new ImageHeader); 368 std::unique_ptr<ImageHeader> cache_hdr(new ImageHeader); 369 if (!ReadSpecificImageHeader(system_filename.c_str(), sys_hdr.get())) { 370 *error_msg = StringPrintf("Unable to read image header for %s at %s", 371 image_location, system_filename.c_str()); 372 return nullptr; 373 } 374 if (!ReadSpecificImageHeader(cache_filename.c_str(), cache_hdr.get())) { 375 *error_msg = StringPrintf("Unable to read image header for %s at %s", 376 image_location, cache_filename.c_str()); 377 return nullptr; 378 } 379 if (sys_hdr->GetOatChecksum() != cache_hdr->GetOatChecksum()) { 380 *error_msg = StringPrintf("Unable to find a relocated version of image file %s", 381 image_location); 382 return nullptr; 383 } 384 return cache_hdr.release(); 385 } else if (!has_cache) { 386 *error_msg = StringPrintf("Unable to find a relocated version of image file %s", 387 image_location); 388 return nullptr; 389 } else if (!has_system && has_cache) { 390 // This can probably just use the cache one. 391 return ReadSpecificImageHeader(cache_filename.c_str(), error_msg); 392 } 393 } else { 394 // We don't want to relocate, Just pick the appropriate one if we have it and return. 395 if (has_system && has_cache) { 396 // We want the cache if the checksum matches, otherwise the system. 397 std::unique_ptr<ImageHeader> system(ReadSpecificImageHeader(system_filename.c_str(), 398 error_msg)); 399 std::unique_ptr<ImageHeader> cache(ReadSpecificImageHeader(cache_filename.c_str(), 400 error_msg)); 401 if (system.get() == nullptr || 402 (cache.get() != nullptr && cache->GetOatChecksum() == system->GetOatChecksum())) { 403 return cache.release(); 404 } else { 405 return system.release(); 406 } 407 } else if (has_system) { 408 return ReadSpecificImageHeader(system_filename.c_str(), error_msg); 409 } else if (has_cache) { 410 return ReadSpecificImageHeader(cache_filename.c_str(), error_msg); 411 } 412 } 413 } 414 415 *error_msg = StringPrintf("Unable to find image file for %s", image_location); 416 return nullptr; 417} 418 419static bool ChecksumsMatch(const char* image_a, const char* image_b) { 420 ImageHeader hdr_a; 421 ImageHeader hdr_b; 422 return ReadSpecificImageHeader(image_a, &hdr_a) && ReadSpecificImageHeader(image_b, &hdr_b) 423 && hdr_a.GetOatChecksum() == hdr_b.GetOatChecksum(); 424} 425 426static bool ImageCreationAllowed(bool is_global_cache, std::string* error_msg) { 427 // Anyone can write into a "local" cache. 428 if (!is_global_cache) { 429 return true; 430 } 431 432 // Only the zygote is allowed to create the global boot image. 433 if (Runtime::Current()->IsZygote()) { 434 return true; 435 } 436 437 *error_msg = "Only the zygote can create the global boot image."; 438 return false; 439} 440 441static constexpr uint64_t kLowSpaceValue = 50 * MB; 442static constexpr uint64_t kTmpFsSentinelValue = 384 * MB; 443 444// Read the free space of the cache partition and make a decision whether to keep the generated 445// image. This is to try to mitigate situations where the system might run out of space later. 446static bool CheckSpace(const std::string& cache_filename, std::string* error_msg) { 447 // Using statvfs vs statvfs64 because of b/18207376, and it is enough for all practical purposes. 448 struct statvfs buf; 449 450 int res = TEMP_FAILURE_RETRY(statvfs(cache_filename.c_str(), &buf)); 451 if (res != 0) { 452 // Could not stat. Conservatively tell the system to delete the image. 453 *error_msg = "Could not stat the filesystem, assuming low-memory situation."; 454 return false; 455 } 456 457 uint64_t fs_overall_size = buf.f_bsize * static_cast<uint64_t>(buf.f_blocks); 458 // Zygote is privileged, but other things are not. Use bavail. 459 uint64_t fs_free_size = buf.f_bsize * static_cast<uint64_t>(buf.f_bavail); 460 461 // Take the overall size as an indicator for a tmpfs, which is being used for the decryption 462 // environment. We do not want to fail quickening the boot image there, as it is beneficial 463 // for time-to-UI. 464 if (fs_overall_size > kTmpFsSentinelValue) { 465 if (fs_free_size < kLowSpaceValue) { 466 *error_msg = StringPrintf("Low-memory situation: only %4.2f megabytes available after image" 467 " generation, need at least %" PRIu64 ".", 468 static_cast<double>(fs_free_size) / MB, 469 kLowSpaceValue / MB); 470 return false; 471 } 472 } 473 return true; 474} 475 476ImageSpace* ImageSpace::Create(const char* image_location, 477 const InstructionSet image_isa, 478 bool secondary_image, 479 std::string* error_msg) { 480 std::string system_filename; 481 bool has_system = false; 482 std::string cache_filename; 483 bool has_cache = false; 484 bool dalvik_cache_exists = false; 485 bool is_global_cache = true; 486 const bool found_image = FindImageFilename(image_location, image_isa, &system_filename, 487 &has_system, &cache_filename, &dalvik_cache_exists, 488 &has_cache, &is_global_cache); 489 490 if (Runtime::Current()->IsZygote() && !secondary_image) { 491 MarkZygoteStart(image_isa, Runtime::Current()->GetZygoteMaxFailedBoots()); 492 } 493 494 ImageSpace* space; 495 bool relocate = Runtime::Current()->ShouldRelocate(); 496 bool can_compile = Runtime::Current()->IsImageDex2OatEnabled(); 497 if (found_image) { 498 const std::string* image_filename; 499 bool is_system = false; 500 bool relocated_version_used = false; 501 if (relocate) { 502 if (!dalvik_cache_exists) { 503 *error_msg = StringPrintf("Requiring relocation for image '%s' at '%s' but we do not have " 504 "any dalvik_cache to find/place it in.", 505 image_location, system_filename.c_str()); 506 return nullptr; 507 } 508 if (has_system) { 509 if (has_cache && ChecksumsMatch(system_filename.c_str(), cache_filename.c_str())) { 510 // We already have a relocated version 511 image_filename = &cache_filename; 512 relocated_version_used = true; 513 } else { 514 // We cannot have a relocated version, Relocate the system one and use it. 515 516 std::string reason; 517 bool success; 518 519 // Check whether we are allowed to relocate. 520 if (!can_compile) { 521 reason = "Image dex2oat disabled by -Xnoimage-dex2oat."; 522 success = false; 523 } else if (!ImageCreationAllowed(is_global_cache, &reason)) { 524 // Whether we can write to the cache. 525 success = false; 526 } else if (secondary_image) { 527 reason = "Should not have to patch secondary image."; 528 success = false; 529 } else { 530 // Try to relocate. 531 success = RelocateImage(image_location, cache_filename.c_str(), image_isa, &reason); 532 } 533 534 if (success) { 535 relocated_version_used = true; 536 image_filename = &cache_filename; 537 } else { 538 *error_msg = StringPrintf("Unable to relocate image '%s' from '%s' to '%s': %s", 539 image_location, system_filename.c_str(), 540 cache_filename.c_str(), reason.c_str()); 541 // We failed to create files, remove any possibly garbage output. 542 // Since ImageCreationAllowed was true above, we are the zygote 543 // and therefore the only process expected to generate these for 544 // the device. 545 PruneDalvikCache(image_isa); 546 return nullptr; 547 } 548 } 549 } else { 550 CHECK(has_cache); 551 // We can just use cache's since it should be fine. This might or might not be relocated. 552 image_filename = &cache_filename; 553 } 554 } else { 555 if (has_system && has_cache) { 556 // Check they have the same cksum. If they do use the cache. Otherwise system. 557 if (ChecksumsMatch(system_filename.c_str(), cache_filename.c_str())) { 558 image_filename = &cache_filename; 559 relocated_version_used = true; 560 } else { 561 image_filename = &system_filename; 562 is_system = true; 563 } 564 } else if (has_system) { 565 image_filename = &system_filename; 566 is_system = true; 567 } else { 568 CHECK(has_cache); 569 image_filename = &cache_filename; 570 } 571 } 572 { 573 // Note that we must not use the file descriptor associated with 574 // ScopedFlock::GetFile to Init the image file. We want the file 575 // descriptor (and the associated exclusive lock) to be released when 576 // we leave Create. 577 ScopedFlock image_lock; 578 image_lock.Init(image_filename->c_str(), error_msg); 579 VLOG(startup) << "Using image file " << image_filename->c_str() << " for image location " 580 << image_location; 581 // If we are in /system we can assume the image is good. We can also 582 // assume this if we are using a relocated image (i.e. image checksum 583 // matches) since this is only different by the offset. We need this to 584 // make sure that host tests continue to work. 585 space = ImageSpace::Init(image_filename->c_str(), image_location, 586 !(is_system || relocated_version_used), error_msg); 587 } 588 if (space != nullptr) { 589 return space; 590 } 591 592 if (relocated_version_used) { 593 // Something is wrong with the relocated copy (even though checksums match). Cleanup. 594 // This can happen if the .oat is corrupt, since the above only checks the .art checksums. 595 // TODO: Check the oat file validity earlier. 596 *error_msg = StringPrintf("Attempted to use relocated version of %s at %s generated from %s " 597 "but image failed to load: %s", 598 image_location, cache_filename.c_str(), system_filename.c_str(), 599 error_msg->c_str()); 600 PruneDalvikCache(image_isa); 601 return nullptr; 602 } else if (is_system) { 603 // If the /system file exists, it should be up-to-date, don't try to generate it. 604 *error_msg = StringPrintf("Failed to load /system image '%s': %s", 605 image_filename->c_str(), error_msg->c_str()); 606 return nullptr; 607 } else { 608 // Otherwise, log a warning and fall through to GenerateImage. 609 LOG(WARNING) << *error_msg; 610 } 611 } 612 613 if (!can_compile) { 614 *error_msg = "Not attempting to compile image because -Xnoimage-dex2oat"; 615 return nullptr; 616 } else if (!dalvik_cache_exists) { 617 *error_msg = StringPrintf("No place to put generated image."); 618 return nullptr; 619 } else if (!ImageCreationAllowed(is_global_cache, error_msg)) { 620 return nullptr; 621 } else if (secondary_image) { 622 *error_msg = "Cannot compile a secondary image."; 623 return nullptr; 624 } else if (!GenerateImage(cache_filename, image_isa, error_msg)) { 625 *error_msg = StringPrintf("Failed to generate image '%s': %s", 626 cache_filename.c_str(), error_msg->c_str()); 627 // We failed to create files, remove any possibly garbage output. 628 // Since ImageCreationAllowed was true above, we are the zygote 629 // and therefore the only process expected to generate these for 630 // the device. 631 PruneDalvikCache(image_isa); 632 return nullptr; 633 } else { 634 // Check whether there is enough space left over after we have generated the image. 635 if (!CheckSpace(cache_filename, error_msg)) { 636 // No. Delete the generated image and try to run out of the dex files. 637 PruneDalvikCache(image_isa); 638 return nullptr; 639 } 640 641 // Note that we must not use the file descriptor associated with 642 // ScopedFlock::GetFile to Init the image file. We want the file 643 // descriptor (and the associated exclusive lock) to be released when 644 // we leave Create. 645 ScopedFlock image_lock; 646 image_lock.Init(cache_filename.c_str(), error_msg); 647 space = ImageSpace::Init(cache_filename.c_str(), image_location, true, error_msg); 648 if (space == nullptr) { 649 *error_msg = StringPrintf("Failed to load generated image '%s': %s", 650 cache_filename.c_str(), error_msg->c_str()); 651 } 652 return space; 653 } 654} 655 656void ImageSpace::VerifyImageAllocations() { 657 uint8_t* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment); 658 while (current < End()) { 659 CHECK_ALIGNED(current, kObjectAlignment); 660 auto* obj = reinterpret_cast<mirror::Object*>(current); 661 CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class"; 662 CHECK(live_bitmap_->Test(obj)) << PrettyTypeOf(obj); 663 if (kUseBakerOrBrooksReadBarrier) { 664 obj->AssertReadBarrierPointer(); 665 } 666 current += RoundUp(obj->SizeOf(), kObjectAlignment); 667 } 668} 669 670ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_location, 671 bool validate_oat_file, std::string* error_msg) { 672 CHECK(image_filename != nullptr); 673 CHECK(image_location != nullptr); 674 675 uint64_t start_time = 0; 676 if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) { 677 start_time = NanoTime(); 678 LOG(INFO) << "ImageSpace::Init entering image_filename=" << image_filename; 679 } 680 681 std::unique_ptr<File> file(OS::OpenFileForReading(image_filename)); 682 if (file.get() == nullptr) { 683 *error_msg = StringPrintf("Failed to open '%s'", image_filename); 684 return nullptr; 685 } 686 ImageHeader image_header; 687 bool success = file->ReadFully(&image_header, sizeof(image_header)); 688 if (!success || !image_header.IsValid()) { 689 *error_msg = StringPrintf("Invalid image header in '%s'", image_filename); 690 return nullptr; 691 } 692 // Check that the file is larger or equal to the header size + data size. 693 const uint64_t image_file_size = static_cast<uint64_t>(file->GetLength()); 694 if (image_file_size < sizeof(ImageHeader) + image_header.GetDataSize()) { 695 *error_msg = StringPrintf("Image file truncated: %" PRIu64 " vs. %" PRIu64 ".", 696 image_file_size, 697 image_header.GetDataSize()); 698 return nullptr; 699 } 700 701 if (VLOG_IS_ON(startup)) { 702 LOG(INFO) << "Dumping image sections"; 703 for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) { 704 const auto section_idx = static_cast<ImageHeader::ImageSections>(i); 705 auto& section = image_header.GetImageSection(section_idx); 706 LOG(INFO) << section_idx << " start=" 707 << reinterpret_cast<void*>(image_header.GetImageBegin() + section.Offset()) << " " 708 << section; 709 } 710 } 711 712 const auto& bitmap_section = image_header.GetImageSection(ImageHeader::kSectionImageBitmap); 713 // The location we want to map from is the first aligned page after the end of the stored 714 // (possibly compressed) data. 715 const size_t image_bitmap_offset = RoundUp(sizeof(image_header) + image_header.GetDataSize(), 716 kPageSize); 717 const size_t end_of_bitmap = image_bitmap_offset + bitmap_section.Size(); 718 if (end_of_bitmap != image_file_size) { 719 *error_msg = StringPrintf( 720 "Image file size does not equal end of bitmap: size=%" PRIu64 " vs. %zu.", image_file_size, 721 end_of_bitmap); 722 return nullptr; 723 } 724 725 // Note: The image header is part of the image due to mmap page alignment required of offset. 726 std::unique_ptr<MemMap> map; 727 if (image_header.GetStorageMode() == ImageHeader::kStorageModeUncompressed) { 728 map.reset(MemMap::MapFileAtAddress(image_header.GetImageBegin(), 729 image_header.GetImageSize(), 730 PROT_READ | PROT_WRITE, 731 MAP_PRIVATE, 732 file->Fd(), 733 0, 734 /*low_4gb*/false, 735 /*reuse*/false, 736 image_filename, 737 error_msg)); 738 } else { 739 // Reserve output and decompress into it. 740 map.reset(MemMap::MapAnonymous(image_location, 741 image_header.GetImageBegin(), 742 image_header.GetImageSize(), 743 PROT_READ | PROT_WRITE, 744 /*low_4gb*/false, 745 /*reuse*/false, 746 error_msg)); 747 if (map != nullptr) { 748 const size_t stored_size = image_header.GetDataSize(); 749 const size_t write_offset = sizeof(image_header); // Skip the header. 750 std::unique_ptr<MemMap> temp_map(MemMap::MapFile(sizeof(ImageHeader) + stored_size, 751 PROT_READ, 752 MAP_PRIVATE, 753 file->Fd(), 754 /*offset*/0, 755 /*low_4gb*/false, 756 image_filename, 757 error_msg)); 758 if (temp_map == nullptr) { 759 DCHECK(!error_msg->empty()); 760 return nullptr; 761 } 762 memcpy(map->Begin(), &image_header, sizeof(image_header)); 763 const uint64_t start = NanoTime(); 764 const size_t decompressed_size = LZ4_decompress_safe( 765 reinterpret_cast<char*>(temp_map->Begin()) + sizeof(ImageHeader), 766 reinterpret_cast<char*>(map->Begin()) + write_offset, 767 stored_size, 768 map->Size()); 769 // TODO: VLOG(image) 770 VLOG(class_linker) << "Decompressing image took " << PrettyDuration(NanoTime() - start); 771 if (decompressed_size + sizeof(ImageHeader) != image_header.GetImageSize()) { 772 *error_msg = StringPrintf("Decompressed size does not match expected image size %zu vs %zu", 773 decompressed_size + sizeof(ImageHeader), 774 image_header.GetImageSize()); 775 return nullptr; 776 } 777 } 778 } 779 780 if (map == nullptr) { 781 DCHECK(!error_msg->empty()); 782 return nullptr; 783 } 784 CHECK_EQ(image_header.GetImageBegin(), map->Begin()); 785 DCHECK_EQ(0, memcmp(&image_header, map->Begin(), sizeof(ImageHeader))); 786 787 std::unique_ptr<MemMap> image_bitmap_map(MemMap::MapFileAtAddress(nullptr, 788 bitmap_section.Size(), 789 PROT_READ, MAP_PRIVATE, 790 file->Fd(), 791 image_bitmap_offset, 792 /*low_4gb*/false, 793 /*reuse*/false, 794 image_filename, 795 error_msg)); 796 if (image_bitmap_map == nullptr) { 797 *error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str()); 798 return nullptr; 799 } 800 uint32_t bitmap_index = bitmap_index_.FetchAndAddSequentiallyConsistent(1); 801 std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", image_filename, 802 bitmap_index)); 803 std::unique_ptr<accounting::ContinuousSpaceBitmap> bitmap( 804 accounting::ContinuousSpaceBitmap::CreateFromMemMap( 805 bitmap_name, 806 image_bitmap_map.release(), 807 reinterpret_cast<uint8_t*>(map->Begin()), 808 accounting::ContinuousSpaceBitmap::ComputeHeapSize(bitmap_section.Size()))); 809 if (bitmap == nullptr) { 810 *error_msg = StringPrintf("Could not create bitmap '%s'", bitmap_name.c_str()); 811 return nullptr; 812 } 813 814 // In case of multi-images, the images are spaced apart so that the bitmaps don't overlap. We 815 // need to reserve the slack, as otherwise the large object space might allocate in there. 816 // TODO: Reconsider the multi-image layout. b/26317072 817 std::unique_ptr<MemMap> shadow_map; 818 { 819 uintptr_t image_begin = reinterpret_cast<uintptr_t>(image_header.GetImageBegin()); 820 uintptr_t image_end = RoundUp(image_begin + image_header.GetImageSize(), kPageSize); 821 uintptr_t oat_begin = reinterpret_cast<uintptr_t>(image_header.GetOatFileBegin()); 822 if (image_end < oat_begin) { 823 // There's a gap. Could be multi-image, could be the oat file spaced apart. Go ahead and 824 // dummy-reserve the space covered by the bitmap (which will be a shadow that introduces 825 // a gap to the next image). 826 uintptr_t heap_size = bitmap->HeapSize(); 827 uintptr_t bitmap_coverage_end = RoundUp(image_begin + heap_size, kPageSize); 828 if (bitmap_coverage_end > image_end) { 829 VLOG(startup) << "Reserving bitmap shadow [" 830 << std::hex << image_end << ";" 831 << std::hex << bitmap_coverage_end << ";] (oat file begins at " 832 << std::hex << oat_begin; 833 // Note: we cannot use MemMap::Dummy here, as that won't reserve the space in 32-bit mode. 834 shadow_map.reset(MemMap::MapAnonymous("Image bitmap shadow", 835 reinterpret_cast<uint8_t*>(image_end), 836 bitmap_coverage_end - image_end, 837 PROT_NONE, 838 false, 839 false, 840 error_msg)); 841 if (shadow_map == nullptr) { 842 return nullptr; 843 } 844 // madvise it away, we don't really want it, just reserve the address space. 845 // TODO: Should we use MadviseDontNeedAndZero? b/26317072 846 madvise(shadow_map->BaseBegin(), shadow_map->BaseSize(), MADV_DONTNEED); 847 } 848 } 849 } 850 851 // We only want the mirror object, not the ArtFields and ArtMethods. 852 uint8_t* const image_end = 853 map->Begin() + image_header.GetImageSection(ImageHeader::kSectionObjects).End(); 854 std::unique_ptr<ImageSpace> space(new ImageSpace(image_filename, 855 image_location, 856 map.release(), 857 bitmap.release(), 858 image_end, 859 shadow_map.release())); 860 861 // VerifyImageAllocations() will be called later in Runtime::Init() 862 // as some class roots like ArtMethod::java_lang_reflect_ArtMethod_ 863 // and ArtField::java_lang_reflect_ArtField_, which are used from 864 // Object::SizeOf() which VerifyImageAllocations() calls, are not 865 // set yet at this point. 866 867 space->oat_file_.reset(space->OpenOatFile(image_filename, error_msg)); 868 if (space->oat_file_.get() == nullptr) { 869 DCHECK(!error_msg->empty()); 870 return nullptr; 871 } 872 space->oat_file_non_owned_ = space->oat_file_.get(); 873 874 if (validate_oat_file && !space->ValidateOatFile(error_msg)) { 875 DCHECK(!error_msg->empty()); 876 return nullptr; 877 } 878 879 Runtime* runtime = Runtime::Current(); 880 runtime->SetInstructionSet(space->oat_file_->GetOatHeader().GetInstructionSet()); 881 882 if (!runtime->HasResolutionMethod()) { 883 runtime->SetResolutionMethod(image_header.GetImageMethod(ImageHeader::kResolutionMethod)); 884 runtime->SetImtConflictMethod(image_header.GetImageMethod(ImageHeader::kImtConflictMethod)); 885 runtime->SetImtUnimplementedMethod( 886 image_header.GetImageMethod(ImageHeader::kImtUnimplementedMethod)); 887 runtime->SetCalleeSaveMethod( 888 image_header.GetImageMethod(ImageHeader::kCalleeSaveMethod), Runtime::kSaveAll); 889 runtime->SetCalleeSaveMethod( 890 image_header.GetImageMethod(ImageHeader::kRefsOnlySaveMethod), Runtime::kRefsOnly); 891 runtime->SetCalleeSaveMethod( 892 image_header.GetImageMethod(ImageHeader::kRefsAndArgsSaveMethod), Runtime::kRefsAndArgs); 893 } 894 895 if (VLOG_IS_ON(heap) || VLOG_IS_ON(startup)) { 896 LOG(INFO) << "ImageSpace::Init exiting (" << PrettyDuration(NanoTime() - start_time) 897 << ") " << *space.get(); 898 } 899 return space.release(); 900} 901 902OatFile* ImageSpace::OpenOatFile(const char* image_path, std::string* error_msg) const { 903 const ImageHeader& image_header = GetImageHeader(); 904 std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(image_path); 905 906 CHECK(image_header.GetOatDataBegin() != nullptr); 907 908 OatFile* oat_file = OatFile::Open(oat_filename, 909 oat_filename, 910 image_header.GetOatDataBegin(), 911 image_header.GetOatFileBegin(), 912 !Runtime::Current()->IsAotCompiler(), 913 nullptr, 914 error_msg); 915 if (oat_file == nullptr) { 916 *error_msg = StringPrintf("Failed to open oat file '%s' referenced from image %s: %s", 917 oat_filename.c_str(), GetName(), error_msg->c_str()); 918 return nullptr; 919 } 920 uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum(); 921 uint32_t image_oat_checksum = image_header.GetOatChecksum(); 922 if (oat_checksum != image_oat_checksum) { 923 *error_msg = StringPrintf("Failed to match oat file checksum 0x%x to expected oat checksum 0x%x" 924 " in image %s", oat_checksum, image_oat_checksum, GetName()); 925 return nullptr; 926 } 927 int32_t image_patch_delta = image_header.GetPatchDelta(); 928 int32_t oat_patch_delta = oat_file->GetOatHeader().GetImagePatchDelta(); 929 if (oat_patch_delta != image_patch_delta && !image_header.CompilePic()) { 930 // We should have already relocated by this point. Bail out. 931 *error_msg = StringPrintf("Failed to match oat file patch delta %d to expected patch delta %d " 932 "in image %s", oat_patch_delta, image_patch_delta, GetName()); 933 return nullptr; 934 } 935 936 return oat_file; 937} 938 939bool ImageSpace::ValidateOatFile(std::string* error_msg) const { 940 CHECK(oat_file_.get() != nullptr); 941 for (const OatFile::OatDexFile* oat_dex_file : oat_file_->GetOatDexFiles()) { 942 const std::string& dex_file_location = oat_dex_file->GetDexFileLocation(); 943 uint32_t dex_file_location_checksum; 944 if (!DexFile::GetChecksum(dex_file_location.c_str(), &dex_file_location_checksum, error_msg)) { 945 *error_msg = StringPrintf("Failed to get checksum of dex file '%s' referenced by image %s: " 946 "%s", dex_file_location.c_str(), GetName(), error_msg->c_str()); 947 return false; 948 } 949 if (dex_file_location_checksum != oat_dex_file->GetDexFileLocationChecksum()) { 950 *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file '%s' and " 951 "dex file '%s' (0x%x != 0x%x)", 952 oat_file_->GetLocation().c_str(), dex_file_location.c_str(), 953 oat_dex_file->GetDexFileLocationChecksum(), 954 dex_file_location_checksum); 955 return false; 956 } 957 } 958 return true; 959} 960 961const OatFile* ImageSpace::GetOatFile() const { 962 return oat_file_non_owned_; 963} 964 965std::unique_ptr<const OatFile> ImageSpace::ReleaseOatFile() { 966 CHECK(oat_file_ != nullptr); 967 return std::move(oat_file_); 968} 969 970void ImageSpace::Dump(std::ostream& os) const { 971 os << GetType() 972 << " begin=" << reinterpret_cast<void*>(Begin()) 973 << ",end=" << reinterpret_cast<void*>(End()) 974 << ",size=" << PrettySize(Size()) 975 << ",name=\"" << GetName() << "\"]"; 976} 977 978void ImageSpace::CreateMultiImageLocations(const std::string& input_image_file_name, 979 const std::string& boot_classpath, 980 std::vector<std::string>* image_file_names) { 981 DCHECK(image_file_names != nullptr); 982 983 std::vector<std::string> images; 984 Split(boot_classpath, ':', &images); 985 986 // Add the rest into the list. We have to adjust locations, possibly: 987 // 988 // For example, image_file_name is /a/b/c/d/e.art 989 // images[0] is f/c/d/e.art 990 // ---------------------------------------------- 991 // images[1] is g/h/i/j.art -> /a/b/h/i/j.art 992 993 // Derive pattern. 994 std::vector<std::string> left; 995 Split(input_image_file_name, '/', &left); 996 std::vector<std::string> right; 997 Split(images[0], '/', &right); 998 999 size_t common = 1; 1000 while (common < left.size() && common < right.size()) { 1001 if (left[left.size() - common - 1] != right[right.size() - common - 1]) { 1002 break; 1003 } 1004 common++; 1005 } 1006 1007 std::vector<std::string> prefix_vector(left.begin(), left.end() - common); 1008 std::string common_prefix = Join(prefix_vector, '/'); 1009 if (!common_prefix.empty() && common_prefix[0] != '/' && input_image_file_name[0] == '/') { 1010 common_prefix = "/" + common_prefix; 1011 } 1012 1013 // Apply pattern to images[1] .. images[n]. 1014 for (size_t i = 1; i < images.size(); ++i) { 1015 std::string image = images[i]; 1016 1017 size_t rslash = std::string::npos; 1018 for (size_t j = 0; j < common; ++j) { 1019 if (rslash != std::string::npos) { 1020 rslash--; 1021 } 1022 1023 rslash = image.rfind('/', rslash); 1024 if (rslash == std::string::npos) { 1025 rslash = 0; 1026 } 1027 if (rslash == 0) { 1028 break; 1029 } 1030 } 1031 std::string image_part = image.substr(rslash); 1032 1033 std::string new_image = common_prefix + (StartsWith(image_part, "/") ? "" : "/") + 1034 image_part; 1035 image_file_names->push_back(new_image); 1036 } 1037} 1038 1039} // namespace space 1040} // namespace gc 1041} // namespace art 1042