image_space.cc revision 05752398db7f25d7892b62cb39615eee468f1db8
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 <lz4.h> 20#include <random> 21#include <sys/statvfs.h> 22#include <sys/types.h> 23#include <unistd.h> 24 25#include "art_method.h" 26#include "base/macros.h" 27#include "base/stl_util.h" 28#include "base/scoped_flock.h" 29#include "base/systrace.h" 30#include "base/time_utils.h" 31#include "gc/accounting/space_bitmap-inl.h" 32#include "image-inl.h" 33#include "image_space_fs.h" 34#include "mirror/class-inl.h" 35#include "mirror/object-inl.h" 36#include "oat_file.h" 37#include "os.h" 38#include "space-inl.h" 39#include "utils.h" 40 41namespace art { 42namespace gc { 43namespace space { 44 45Atomic<uint32_t> ImageSpace::bitmap_index_(0); 46 47ImageSpace::ImageSpace(const std::string& image_filename, 48 const char* image_location, 49 MemMap* mem_map, 50 accounting::ContinuousSpaceBitmap* live_bitmap, 51 uint8_t* end) 52 : MemMapSpace(image_filename, 53 mem_map, 54 mem_map->Begin(), 55 end, 56 end, 57 kGcRetentionPolicyNeverCollect), 58 oat_file_non_owned_(nullptr), 59 image_location_(image_location) { 60 DCHECK(live_bitmap != nullptr); 61 live_bitmap_.reset(live_bitmap); 62} 63 64static int32_t ChooseRelocationOffsetDelta(int32_t min_delta, int32_t max_delta) { 65 CHECK_ALIGNED(min_delta, kPageSize); 66 CHECK_ALIGNED(max_delta, kPageSize); 67 CHECK_LT(min_delta, max_delta); 68 69 int32_t r = GetRandomNumber<int32_t>(min_delta, max_delta); 70 if (r % 2 == 0) { 71 r = RoundUp(r, kPageSize); 72 } else { 73 r = RoundDown(r, kPageSize); 74 } 75 CHECK_LE(min_delta, r); 76 CHECK_GE(max_delta, r); 77 CHECK_ALIGNED(r, kPageSize); 78 return r; 79} 80 81static bool GenerateImage(const std::string& image_filename, InstructionSet image_isa, 82 std::string* error_msg) { 83 const std::string boot_class_path_string(Runtime::Current()->GetBootClassPathString()); 84 std::vector<std::string> boot_class_path; 85 Split(boot_class_path_string, ':', &boot_class_path); 86 if (boot_class_path.empty()) { 87 *error_msg = "Failed to generate image because no boot class path specified"; 88 return false; 89 } 90 // We should clean up so we are more likely to have room for the image. 91 if (Runtime::Current()->IsZygote()) { 92 LOG(INFO) << "Pruning dalvik-cache since we are generating an image and will need to recompile"; 93 PruneDalvikCache(image_isa); 94 } 95 96 std::vector<std::string> arg_vector; 97 98 std::string dex2oat(Runtime::Current()->GetCompilerExecutable()); 99 arg_vector.push_back(dex2oat); 100 101 std::string image_option_string("--image="); 102 image_option_string += image_filename; 103 arg_vector.push_back(image_option_string); 104 105 for (size_t i = 0; i < boot_class_path.size(); i++) { 106 arg_vector.push_back(std::string("--dex-file=") + boot_class_path[i]); 107 } 108 109 std::string oat_file_option_string("--oat-file="); 110 oat_file_option_string += ImageHeader::GetOatLocationFromImageLocation(image_filename); 111 arg_vector.push_back(oat_file_option_string); 112 113 // Note: we do not generate a fully debuggable boot image so we do not pass the 114 // compiler flag --debuggable here. 115 116 Runtime::Current()->AddCurrentRuntimeFeaturesAsDex2OatArguments(&arg_vector); 117 CHECK_EQ(image_isa, kRuntimeISA) 118 << "We should always be generating an image for the current isa."; 119 120 int32_t base_offset = ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, 121 ART_BASE_ADDRESS_MAX_DELTA); 122 LOG(INFO) << "Using an offset of 0x" << std::hex << base_offset << " from default " 123 << "art base address of 0x" << std::hex << ART_BASE_ADDRESS; 124 arg_vector.push_back(StringPrintf("--base=0x%x", ART_BASE_ADDRESS + base_offset)); 125 126 if (!kIsTargetBuild) { 127 arg_vector.push_back("--host"); 128 } 129 130 const std::vector<std::string>& compiler_options = Runtime::Current()->GetImageCompilerOptions(); 131 for (size_t i = 0; i < compiler_options.size(); ++i) { 132 arg_vector.push_back(compiler_options[i].c_str()); 133 } 134 135 std::string command_line(Join(arg_vector, ' ')); 136 LOG(INFO) << "GenerateImage: " << command_line; 137 return Exec(arg_vector, error_msg); 138} 139 140bool ImageSpace::FindImageFilename(const char* image_location, 141 const InstructionSet image_isa, 142 std::string* system_filename, 143 bool* has_system, 144 std::string* cache_filename, 145 bool* dalvik_cache_exists, 146 bool* has_cache, 147 bool* is_global_cache) { 148 *has_system = false; 149 *has_cache = false; 150 // image_location = /system/framework/boot.art 151 // system_image_location = /system/framework/<image_isa>/boot.art 152 std::string system_image_filename(GetSystemImageFilename(image_location, image_isa)); 153 if (OS::FileExists(system_image_filename.c_str())) { 154 *system_filename = system_image_filename; 155 *has_system = true; 156 } 157 158 bool have_android_data = false; 159 *dalvik_cache_exists = false; 160 std::string dalvik_cache; 161 GetDalvikCache(GetInstructionSetString(image_isa), true, &dalvik_cache, 162 &have_android_data, dalvik_cache_exists, is_global_cache); 163 164 if (have_android_data && *dalvik_cache_exists) { 165 // Always set output location even if it does not exist, 166 // so that the caller knows where to create the image. 167 // 168 // image_location = /system/framework/boot.art 169 // *image_filename = /data/dalvik-cache/<image_isa>/boot.art 170 std::string error_msg; 171 if (!GetDalvikCacheFilename(image_location, dalvik_cache.c_str(), cache_filename, &error_msg)) { 172 LOG(WARNING) << error_msg; 173 return *has_system; 174 } 175 *has_cache = OS::FileExists(cache_filename->c_str()); 176 } 177 return *has_system || *has_cache; 178} 179 180static bool ReadSpecificImageHeader(const char* filename, ImageHeader* image_header) { 181 std::unique_ptr<File> image_file(OS::OpenFileForReading(filename)); 182 if (image_file.get() == nullptr) { 183 return false; 184 } 185 const bool success = image_file->ReadFully(image_header, sizeof(ImageHeader)); 186 if (!success || !image_header->IsValid()) { 187 return false; 188 } 189 return true; 190} 191 192// Relocate the image at image_location to dest_filename and relocate it by a random amount. 193static bool RelocateImage(const char* image_location, const char* dest_filename, 194 InstructionSet isa, std::string* error_msg) { 195 // We should clean up so we are more likely to have room for the image. 196 if (Runtime::Current()->IsZygote()) { 197 LOG(INFO) << "Pruning dalvik-cache since we are relocating an image and will need to recompile"; 198 PruneDalvikCache(isa); 199 } 200 201 std::string patchoat(Runtime::Current()->GetPatchoatExecutable()); 202 203 std::string input_image_location_arg("--input-image-location="); 204 input_image_location_arg += image_location; 205 206 std::string output_image_filename_arg("--output-image-file="); 207 output_image_filename_arg += dest_filename; 208 209 std::string instruction_set_arg("--instruction-set="); 210 instruction_set_arg += GetInstructionSetString(isa); 211 212 std::string base_offset_arg("--base-offset-delta="); 213 StringAppendF(&base_offset_arg, "%d", ChooseRelocationOffsetDelta(ART_BASE_ADDRESS_MIN_DELTA, 214 ART_BASE_ADDRESS_MAX_DELTA)); 215 216 std::vector<std::string> argv; 217 argv.push_back(patchoat); 218 219 argv.push_back(input_image_location_arg); 220 argv.push_back(output_image_filename_arg); 221 222 argv.push_back(instruction_set_arg); 223 argv.push_back(base_offset_arg); 224 225 std::string command_line(Join(argv, ' ')); 226 LOG(INFO) << "RelocateImage: " << command_line; 227 return Exec(argv, error_msg); 228} 229 230static ImageHeader* ReadSpecificImageHeader(const char* filename, std::string* error_msg) { 231 std::unique_ptr<ImageHeader> hdr(new ImageHeader); 232 if (!ReadSpecificImageHeader(filename, hdr.get())) { 233 *error_msg = StringPrintf("Unable to read image header for %s", filename); 234 return nullptr; 235 } 236 return hdr.release(); 237} 238 239ImageHeader* ImageSpace::ReadImageHeaderOrDie(const char* image_location, 240 const InstructionSet image_isa) { 241 std::string error_msg; 242 ImageHeader* image_header = ReadImageHeader(image_location, image_isa, &error_msg); 243 if (image_header == nullptr) { 244 LOG(FATAL) << error_msg; 245 } 246 return image_header; 247} 248 249ImageHeader* ImageSpace::ReadImageHeader(const char* image_location, 250 const InstructionSet image_isa, 251 std::string* error_msg) { 252 std::string system_filename; 253 bool has_system = false; 254 std::string cache_filename; 255 bool has_cache = false; 256 bool dalvik_cache_exists = false; 257 bool is_global_cache = false; 258 if (FindImageFilename(image_location, image_isa, &system_filename, &has_system, 259 &cache_filename, &dalvik_cache_exists, &has_cache, &is_global_cache)) { 260 if (Runtime::Current()->ShouldRelocate()) { 261 if (has_system && has_cache) { 262 std::unique_ptr<ImageHeader> sys_hdr(new ImageHeader); 263 std::unique_ptr<ImageHeader> cache_hdr(new ImageHeader); 264 if (!ReadSpecificImageHeader(system_filename.c_str(), sys_hdr.get())) { 265 *error_msg = StringPrintf("Unable to read image header for %s at %s", 266 image_location, system_filename.c_str()); 267 return nullptr; 268 } 269 if (!ReadSpecificImageHeader(cache_filename.c_str(), cache_hdr.get())) { 270 *error_msg = StringPrintf("Unable to read image header for %s at %s", 271 image_location, cache_filename.c_str()); 272 return nullptr; 273 } 274 if (sys_hdr->GetOatChecksum() != cache_hdr->GetOatChecksum()) { 275 *error_msg = StringPrintf("Unable to find a relocated version of image file %s", 276 image_location); 277 return nullptr; 278 } 279 return cache_hdr.release(); 280 } else if (!has_cache) { 281 *error_msg = StringPrintf("Unable to find a relocated version of image file %s", 282 image_location); 283 return nullptr; 284 } else if (!has_system && has_cache) { 285 // This can probably just use the cache one. 286 return ReadSpecificImageHeader(cache_filename.c_str(), error_msg); 287 } 288 } else { 289 // We don't want to relocate, Just pick the appropriate one if we have it and return. 290 if (has_system && has_cache) { 291 // We want the cache if the checksum matches, otherwise the system. 292 std::unique_ptr<ImageHeader> system(ReadSpecificImageHeader(system_filename.c_str(), 293 error_msg)); 294 std::unique_ptr<ImageHeader> cache(ReadSpecificImageHeader(cache_filename.c_str(), 295 error_msg)); 296 if (system.get() == nullptr || 297 (cache.get() != nullptr && cache->GetOatChecksum() == system->GetOatChecksum())) { 298 return cache.release(); 299 } else { 300 return system.release(); 301 } 302 } else if (has_system) { 303 return ReadSpecificImageHeader(system_filename.c_str(), error_msg); 304 } else if (has_cache) { 305 return ReadSpecificImageHeader(cache_filename.c_str(), error_msg); 306 } 307 } 308 } 309 310 *error_msg = StringPrintf("Unable to find image file for %s", image_location); 311 return nullptr; 312} 313 314static bool ChecksumsMatch(const char* image_a, const char* image_b) { 315 ImageHeader hdr_a; 316 ImageHeader hdr_b; 317 return ReadSpecificImageHeader(image_a, &hdr_a) && ReadSpecificImageHeader(image_b, &hdr_b) 318 && hdr_a.GetOatChecksum() == hdr_b.GetOatChecksum(); 319} 320 321static bool ImageCreationAllowed(bool is_global_cache, std::string* error_msg) { 322 // Anyone can write into a "local" cache. 323 if (!is_global_cache) { 324 return true; 325 } 326 327 // Only the zygote is allowed to create the global boot image. 328 if (Runtime::Current()->IsZygote()) { 329 return true; 330 } 331 332 *error_msg = "Only the zygote can create the global boot image."; 333 return false; 334} 335 336static constexpr uint64_t kLowSpaceValue = 50 * MB; 337static constexpr uint64_t kTmpFsSentinelValue = 384 * MB; 338 339// Read the free space of the cache partition and make a decision whether to keep the generated 340// image. This is to try to mitigate situations where the system might run out of space later. 341static bool CheckSpace(const std::string& cache_filename, std::string* error_msg) { 342 // Using statvfs vs statvfs64 because of b/18207376, and it is enough for all practical purposes. 343 struct statvfs buf; 344 345 int res = TEMP_FAILURE_RETRY(statvfs(cache_filename.c_str(), &buf)); 346 if (res != 0) { 347 // Could not stat. Conservatively tell the system to delete the image. 348 *error_msg = "Could not stat the filesystem, assuming low-memory situation."; 349 return false; 350 } 351 352 uint64_t fs_overall_size = buf.f_bsize * static_cast<uint64_t>(buf.f_blocks); 353 // Zygote is privileged, but other things are not. Use bavail. 354 uint64_t fs_free_size = buf.f_bsize * static_cast<uint64_t>(buf.f_bavail); 355 356 // Take the overall size as an indicator for a tmpfs, which is being used for the decryption 357 // environment. We do not want to fail quickening the boot image there, as it is beneficial 358 // for time-to-UI. 359 if (fs_overall_size > kTmpFsSentinelValue) { 360 if (fs_free_size < kLowSpaceValue) { 361 *error_msg = StringPrintf("Low-memory situation: only %4.2f megabytes available after image" 362 " generation, need at least %" PRIu64 ".", 363 static_cast<double>(fs_free_size) / MB, 364 kLowSpaceValue / MB); 365 return false; 366 } 367 } 368 return true; 369} 370 371ImageSpace* ImageSpace::CreateBootImage(const char* image_location, 372 const InstructionSet image_isa, 373 bool secondary_image, 374 std::string* error_msg) { 375 ScopedTrace trace(__FUNCTION__); 376 std::string system_filename; 377 bool has_system = false; 378 std::string cache_filename; 379 bool has_cache = false; 380 bool dalvik_cache_exists = false; 381 bool is_global_cache = true; 382 bool found_image = FindImageFilename(image_location, image_isa, &system_filename, 383 &has_system, &cache_filename, &dalvik_cache_exists, 384 &has_cache, &is_global_cache); 385 386 // If we're starting with the global cache, and we're the zygote, try to see whether there are 387 // OTA artifacts from the A/B OTA preopting to move over. 388 // (It is structurally simpler to check this here, instead of complicating the compile/relocate 389 // logic below.) 390 const bool is_zygote = Runtime::Current()->IsZygote(); 391 if (is_global_cache && is_zygote) { 392 VLOG(startup) << "Checking for A/B OTA data."; 393 TryMoveOTAArtifacts(cache_filename, dalvik_cache_exists); 394 395 // Retry. There are two cases where the old info is outdated: 396 // * There wasn't a boot image before (e.g., some failure on boot), but now the OTA preopted 397 // image has been moved in-place. 398 // * There was a boot image before, and we tried to move the OTA preopted image, but a failure 399 // happened and there is no file anymore. 400 found_image = FindImageFilename(image_location, 401 image_isa, 402 &system_filename, 403 &has_system, 404 &cache_filename, 405 &dalvik_cache_exists, 406 &has_cache, 407 &is_global_cache); 408 } 409 410 if (Runtime::Current()->IsZygote() && !secondary_image) { 411 MarkZygoteStart(image_isa, Runtime::Current()->GetZygoteMaxFailedBoots()); 412 } 413 414 ImageSpace* space; 415 bool relocate = Runtime::Current()->ShouldRelocate(); 416 bool can_compile = Runtime::Current()->IsImageDex2OatEnabled(); 417 if (found_image) { 418 const std::string* image_filename; 419 bool is_system = false; 420 bool relocated_version_used = false; 421 if (relocate) { 422 if (!dalvik_cache_exists) { 423 *error_msg = StringPrintf("Requiring relocation for image '%s' at '%s' but we do not have " 424 "any dalvik_cache to find/place it in.", 425 image_location, system_filename.c_str()); 426 return nullptr; 427 } 428 if (has_system) { 429 if (has_cache && ChecksumsMatch(system_filename.c_str(), cache_filename.c_str())) { 430 // We already have a relocated version 431 image_filename = &cache_filename; 432 relocated_version_used = true; 433 } else { 434 // We cannot have a relocated version, Relocate the system one and use it. 435 436 std::string reason; 437 bool success; 438 439 // Check whether we are allowed to relocate. 440 if (!can_compile) { 441 reason = "Image dex2oat disabled by -Xnoimage-dex2oat."; 442 success = false; 443 } else if (!ImageCreationAllowed(is_global_cache, &reason)) { 444 // Whether we can write to the cache. 445 success = false; 446 } else if (secondary_image) { 447 reason = "Should not have to patch secondary image."; 448 success = false; 449 } else { 450 // Try to relocate. 451 success = RelocateImage(image_location, cache_filename.c_str(), image_isa, &reason); 452 } 453 454 if (success) { 455 relocated_version_used = true; 456 image_filename = &cache_filename; 457 } else { 458 *error_msg = StringPrintf("Unable to relocate image '%s' from '%s' to '%s': %s", 459 image_location, system_filename.c_str(), 460 cache_filename.c_str(), reason.c_str()); 461 // We failed to create files, remove any possibly garbage output. 462 // Since ImageCreationAllowed was true above, we are the zygote 463 // and therefore the only process expected to generate these for 464 // the device. 465 PruneDalvikCache(image_isa); 466 return nullptr; 467 } 468 } 469 } else { 470 CHECK(has_cache); 471 // We can just use cache's since it should be fine. This might or might not be relocated. 472 image_filename = &cache_filename; 473 } 474 } else { 475 if (has_system && has_cache) { 476 // Check they have the same cksum. If they do use the cache. Otherwise system. 477 if (ChecksumsMatch(system_filename.c_str(), cache_filename.c_str())) { 478 image_filename = &cache_filename; 479 relocated_version_used = true; 480 } else { 481 image_filename = &system_filename; 482 is_system = true; 483 } 484 } else if (has_system) { 485 image_filename = &system_filename; 486 is_system = true; 487 } else { 488 CHECK(has_cache); 489 image_filename = &cache_filename; 490 } 491 } 492 { 493 // Note that we must not use the file descriptor associated with 494 // ScopedFlock::GetFile to Init the image file. We want the file 495 // descriptor (and the associated exclusive lock) to be released when 496 // we leave Create. 497 ScopedFlock image_lock; 498 image_lock.Init(image_filename->c_str(), error_msg); 499 VLOG(startup) << "Using image file " << image_filename->c_str() << " for image location " 500 << image_location; 501 // If we are in /system we can assume the image is good. We can also 502 // assume this if we are using a relocated image (i.e. image checksum 503 // matches) since this is only different by the offset. We need this to 504 // make sure that host tests continue to work. 505 // Since we are the boot image, pass null since we load the oat file from the boot image oat 506 // file name. 507 space = ImageSpace::Init(image_filename->c_str(), 508 image_location, 509 !(is_system || relocated_version_used), 510 /* oat_file */nullptr, 511 error_msg); 512 } 513 if (space != nullptr) { 514 return space; 515 } 516 517 if (relocated_version_used) { 518 // Something is wrong with the relocated copy (even though checksums match). Cleanup. 519 // This can happen if the .oat is corrupt, since the above only checks the .art checksums. 520 // TODO: Check the oat file validity earlier. 521 *error_msg = StringPrintf("Attempted to use relocated version of %s at %s generated from %s " 522 "but image failed to load: %s", 523 image_location, cache_filename.c_str(), system_filename.c_str(), 524 error_msg->c_str()); 525 PruneDalvikCache(image_isa); 526 return nullptr; 527 } else if (is_system) { 528 // If the /system file exists, it should be up-to-date, don't try to generate it. 529 *error_msg = StringPrintf("Failed to load /system image '%s': %s", 530 image_filename->c_str(), error_msg->c_str()); 531 return nullptr; 532 } else { 533 // Otherwise, log a warning and fall through to GenerateImage. 534 LOG(WARNING) << *error_msg; 535 } 536 } 537 538 if (!can_compile) { 539 *error_msg = "Not attempting to compile image because -Xnoimage-dex2oat"; 540 return nullptr; 541 } else if (!dalvik_cache_exists) { 542 *error_msg = StringPrintf("No place to put generated image."); 543 return nullptr; 544 } else if (!ImageCreationAllowed(is_global_cache, error_msg)) { 545 return nullptr; 546 } else if (secondary_image) { 547 *error_msg = "Cannot compile a secondary image."; 548 return nullptr; 549 } else if (!GenerateImage(cache_filename, image_isa, error_msg)) { 550 *error_msg = StringPrintf("Failed to generate image '%s': %s", 551 cache_filename.c_str(), error_msg->c_str()); 552 // We failed to create files, remove any possibly garbage output. 553 // Since ImageCreationAllowed was true above, we are the zygote 554 // and therefore the only process expected to generate these for 555 // the device. 556 PruneDalvikCache(image_isa); 557 return nullptr; 558 } else { 559 // Check whether there is enough space left over after we have generated the image. 560 if (!CheckSpace(cache_filename, error_msg)) { 561 // No. Delete the generated image and try to run out of the dex files. 562 PruneDalvikCache(image_isa); 563 return nullptr; 564 } 565 566 // Note that we must not use the file descriptor associated with 567 // ScopedFlock::GetFile to Init the image file. We want the file 568 // descriptor (and the associated exclusive lock) to be released when 569 // we leave Create. 570 ScopedFlock image_lock; 571 image_lock.Init(cache_filename.c_str(), error_msg); 572 space = ImageSpace::Init(cache_filename.c_str(), image_location, true, nullptr, error_msg); 573 if (space == nullptr) { 574 *error_msg = StringPrintf("Failed to load generated image '%s': %s", 575 cache_filename.c_str(), error_msg->c_str()); 576 } 577 return space; 578 } 579} 580 581void ImageSpace::VerifyImageAllocations() { 582 uint8_t* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment); 583 while (current < End()) { 584 CHECK_ALIGNED(current, kObjectAlignment); 585 auto* obj = reinterpret_cast<mirror::Object*>(current); 586 CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class"; 587 CHECK(live_bitmap_->Test(obj)) << PrettyTypeOf(obj); 588 if (kUseBakerOrBrooksReadBarrier) { 589 obj->AssertReadBarrierPointer(); 590 } 591 current += RoundUp(obj->SizeOf(), kObjectAlignment); 592 } 593} 594 595// Helper class for relocating from one range of memory to another. 596class RelocationRange { 597 public: 598 RelocationRange() = default; 599 RelocationRange(const RelocationRange&) = default; 600 RelocationRange(uintptr_t source, uintptr_t dest, uintptr_t length) 601 : source_(source), 602 dest_(dest), 603 length_(length) {} 604 605 bool InSource(uintptr_t address) const { 606 return address - source_ < length_; 607 } 608 609 bool InDest(uintptr_t address) const { 610 return address - dest_ < length_; 611 } 612 613 // Translate a source address to the destination space. 614 uintptr_t ToDest(uintptr_t address) const { 615 DCHECK(InSource(address)); 616 return address + Delta(); 617 } 618 619 // Returns the delta between the dest from the source. 620 off_t Delta() const { 621 return dest_ - source_; 622 } 623 624 uintptr_t Source() const { 625 return source_; 626 } 627 628 uintptr_t Dest() const { 629 return dest_; 630 } 631 632 uintptr_t Length() const { 633 return length_; 634 } 635 636 private: 637 const uintptr_t source_; 638 const uintptr_t dest_; 639 const uintptr_t length_; 640}; 641 642class FixupVisitor : public ValueObject { 643 public: 644 FixupVisitor(const RelocationRange& boot_image, 645 const RelocationRange& boot_oat, 646 const RelocationRange& app_image, 647 const RelocationRange& app_oat) 648 : boot_image_(boot_image), 649 boot_oat_(boot_oat), 650 app_image_(app_image), 651 app_oat_(app_oat) {} 652 653 // Return the relocated address of a heap object. 654 template <typename T> 655 ALWAYS_INLINE T* ForwardObject(T* src) const { 656 const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src); 657 if (boot_image_.InSource(uint_src)) { 658 return reinterpret_cast<T*>(boot_image_.ToDest(uint_src)); 659 } 660 if (app_image_.InSource(uint_src)) { 661 return reinterpret_cast<T*>(app_image_.ToDest(uint_src)); 662 } 663 // Since we are fixing up the app image, there should only be pointers to the app image and 664 // boot image. 665 DCHECK(src == nullptr) << reinterpret_cast<const void*>(src); 666 return src; 667 } 668 669 // Return the relocated address of a code pointer (contained by an oat file). 670 ALWAYS_INLINE const void* ForwardCode(const void* src) const { 671 const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src); 672 if (boot_oat_.InSource(uint_src)) { 673 return reinterpret_cast<const void*>(boot_oat_.ToDest(uint_src)); 674 } 675 if (app_oat_.InSource(uint_src)) { 676 return reinterpret_cast<const void*>(app_oat_.ToDest(uint_src)); 677 } 678 DCHECK(src == nullptr) << src; 679 return src; 680 } 681 682 protected: 683 // Source section. 684 const RelocationRange boot_image_; 685 const RelocationRange boot_oat_; 686 const RelocationRange app_image_; 687 const RelocationRange app_oat_; 688}; 689 690std::ostream& operator<<(std::ostream& os, const RelocationRange& reloc) { 691 return os << "(" << reinterpret_cast<const void*>(reloc.Source()) << "-" 692 << reinterpret_cast<const void*>(reloc.Source() + reloc.Length()) << ")->(" 693 << reinterpret_cast<const void*>(reloc.Dest()) << "-" 694 << reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")"; 695} 696 697// Adapt for mirror::Class::FixupNativePointers. 698class FixupObjectAdapter : public FixupVisitor { 699 public: 700 template<typename... Args> 701 explicit FixupObjectAdapter(Args... args) : FixupVisitor(args...) {} 702 703 // Must be called on pointers that already have been relocated to the destination relocation. 704 ALWAYS_INLINE bool IsInAppImage(mirror::Object* object) const { 705 return app_image_.InDest(reinterpret_cast<uintptr_t>(object)); 706 } 707 708 template <typename T> 709 T* operator()(T* obj) const { 710 return ForwardObject(obj); 711 } 712}; 713 714class FixupClassVisitor : public FixupVisitor { 715 public: 716 template<typename... Args> 717 explicit FixupClassVisitor(Args... args) : FixupVisitor(args...) {} 718 719 // The image space is contained so the GC doesn't need to know about it. Avoid requiring mutator 720 // lock to prevent possible pauses. 721 ALWAYS_INLINE void operator()(mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS { 722 mirror::Class* klass = obj->GetClass<kVerifyNone, kWithoutReadBarrier>(); 723 DCHECK(klass != nullptr) << "Null class in image"; 724 // No AsClass since our fields aren't quite fixed up yet. 725 mirror::Class* new_klass = down_cast<mirror::Class*>(ForwardObject(klass)); 726 // Keep clean if possible. 727 if (klass != new_klass) { 728 obj->SetClass<kVerifyNone>(new_klass); 729 } 730 } 731}; 732 733class FixupRootVisitor : public FixupVisitor { 734 public: 735 template<typename... Args> 736 explicit FixupRootVisitor(Args... args) : FixupVisitor(args...) {} 737 738 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const 739 SHARED_REQUIRES(Locks::mutator_lock_) { 740 if (!root->IsNull()) { 741 VisitRoot(root); 742 } 743 } 744 745 ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const 746 SHARED_REQUIRES(Locks::mutator_lock_) { 747 mirror::Object* ref = root->AsMirrorPtr(); 748 mirror::Object* new_ref = ForwardObject(ref); 749 if (ref != new_ref) { 750 root->Assign(new_ref); 751 } 752 } 753}; 754 755class FixupObjectVisitor : public FixupVisitor { 756 public: 757 template<typename... Args> 758 explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* pointer_array_visited, 759 Args... args) 760 : FixupVisitor(args...), 761 pointer_array_visited_(pointer_array_visited) {} 762 763 // Fix up separately since we also need to fix up method entrypoints. 764 ALWAYS_INLINE void VisitRootIfNonNull( 765 mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) const {} 766 767 ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root ATTRIBUTE_UNUSED) 768 const {} 769 770 ALWAYS_INLINE void operator()(mirror::Object* obj, 771 MemberOffset offset, 772 bool is_static ATTRIBUTE_UNUSED) const 773 NO_THREAD_SAFETY_ANALYSIS { 774 // There could be overlap between ranges, we must avoid visiting the same reference twice. 775 // Avoid the class field since we already fixed it up in FixupClassVisitor. 776 if (offset.Uint32Value() != mirror::Object::ClassOffset().Uint32Value()) { 777 // Space is not yet added to the heap, don't do a read barrier. 778 mirror::Object* ref = obj->GetFieldObject<mirror::Object, kVerifyNone, kWithoutReadBarrier>( 779 offset); 780 // Use SetFieldObjectWithoutWriteBarrier to avoid card marking since we are writing to the 781 // image. 782 obj->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>(offset, ForwardObject(ref)); 783 } 784 } 785 786 // Visit a pointer array and forward corresponding native data. Ignores pointer arrays in the 787 // boot image. Uses the bitmap to ensure the same array is not visited multiple times. 788 template <typename Visitor> 789 void VisitPointerArray(mirror::PointerArray* array, const Visitor& visitor) const 790 NO_THREAD_SAFETY_ANALYSIS { 791 if (array != nullptr && 792 visitor.IsInAppImage(array) && 793 !pointer_array_visited_->Test(array)) { 794 array->Fixup<kVerifyNone, kWithoutReadBarrier>(array, sizeof(void*), visitor); 795 pointer_array_visited_->Set(array); 796 } 797 } 798 799 // java.lang.ref.Reference visitor. 800 void operator()(mirror::Class* klass ATTRIBUTE_UNUSED, mirror::Reference* ref) const 801 SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) { 802 mirror::Object* obj = ref->GetReferent<kWithoutReadBarrier>(); 803 ref->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>( 804 mirror::Reference::ReferentOffset(), 805 ForwardObject(obj)); 806 } 807 808 ALWAYS_INLINE void operator()(mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS { 809 obj->VisitReferences</*visit native roots*/false, kVerifyNone, kWithoutReadBarrier>( 810 *this, 811 *this); 812 // We want to use our own class loader and not the one in the image. 813 if (obj->IsClass<kVerifyNone, kWithoutReadBarrier>()) { 814 mirror::Class* klass = obj->AsClass<kVerifyNone, kWithoutReadBarrier>(); 815 FixupObjectAdapter visitor(boot_image_, boot_oat_, app_image_, app_oat_); 816 klass->FixupNativePointers<kVerifyNone, kWithoutReadBarrier>(klass, sizeof(void*), visitor); 817 // Deal with the pointer arrays. Use the helper function since multiple classes can reference 818 // the same arrays. 819 VisitPointerArray(klass->GetVTable<kVerifyNone, kWithoutReadBarrier>(), visitor); 820 mirror::IfTable* iftable = klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>(); 821 if (iftable != nullptr) { 822 for (int32_t i = 0, count = iftable->Count(); i < count; ++i) { 823 if (iftable->GetMethodArrayCount<kVerifyNone, kWithoutReadBarrier>(i) > 0) { 824 mirror::PointerArray* methods = 825 iftable->GetMethodArray<kVerifyNone, kWithoutReadBarrier>(i); 826 DCHECK(methods != nullptr); 827 VisitPointerArray(methods, visitor); 828 } 829 } 830 } 831 } 832 } 833 834 private: 835 gc::accounting::ContinuousSpaceBitmap* const pointer_array_visited_; 836}; 837 838class ForwardObjectAdapter { 839 public: 840 ALWAYS_INLINE ForwardObjectAdapter(const FixupVisitor* visitor) : visitor_(visitor) {} 841 842 template <typename T> 843 ALWAYS_INLINE T* operator()(T* src) const { 844 return visitor_->ForwardObject(src); 845 } 846 847 private: 848 const FixupVisitor* const visitor_; 849}; 850 851class ForwardCodeAdapter { 852 public: 853 ALWAYS_INLINE ForwardCodeAdapter(const FixupVisitor* visitor) : visitor_(visitor) {} 854 855 template <typename T> 856 ALWAYS_INLINE T* operator()(T* src) const { 857 return visitor_->ForwardCode(src); 858 } 859 860 private: 861 const FixupVisitor* const visitor_; 862}; 863 864class FixupArtMethodVisitor : public FixupVisitor, public ArtMethodVisitor { 865 public: 866 template<typename... Args> 867 explicit FixupArtMethodVisitor(bool fixup_heap_objects, Args... args) 868 : FixupVisitor(args...), 869 fixup_heap_objects_(fixup_heap_objects) {} 870 871 virtual void Visit(ArtMethod* method) NO_THREAD_SAFETY_ANALYSIS { 872 if (fixup_heap_objects_) { 873 method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this)); 874 } 875 method->UpdateEntrypoints<kWithoutReadBarrier>(ForwardCodeAdapter(this)); 876 } 877 878 private: 879 const bool fixup_heap_objects_; 880}; 881 882class FixupArtFieldVisitor : public FixupVisitor, public ArtFieldVisitor { 883 public: 884 template<typename... Args> 885 explicit FixupArtFieldVisitor(Args... args) : FixupVisitor(args...) {} 886 887 virtual void Visit(ArtField* field) NO_THREAD_SAFETY_ANALYSIS { 888 field->UpdateObjects(ForwardObjectAdapter(this)); 889 } 890}; 891 892// Relocate an image space mapped at target_base which possibly used to be at a different base 893// address. Only needs a single image space, not one for both source and destination. 894// In place means modifying a single ImageSpace in place rather than relocating from one ImageSpace 895// to another. 896static bool RelocateInPlace(ImageHeader& image_header, 897 uint8_t* target_base, 898 accounting::ContinuousSpaceBitmap* bitmap, 899 const OatFile* app_oat_file, 900 std::string* error_msg) { 901 DCHECK(error_msg != nullptr); 902 if (!image_header.IsPic()) { 903 if (image_header.GetImageBegin() == target_base) { 904 return true; 905 } 906 *error_msg = StringPrintf("Cannot relocate non-pic image for oat file %s", 907 (app_oat_file != nullptr) ? app_oat_file->GetLocation().c_str() : ""); 908 return false; 909 } 910 // Set up sections. 911 uint32_t boot_image_begin = 0; 912 uint32_t boot_image_end = 0; 913 uint32_t boot_oat_begin = 0; 914 uint32_t boot_oat_end = 0; 915 gc::Heap* const heap = Runtime::Current()->GetHeap(); 916 heap->GetBootImagesSize(&boot_image_begin, &boot_image_end, &boot_oat_begin, &boot_oat_end); 917 CHECK_NE(boot_image_begin, boot_image_end) 918 << "Can not relocate app image without boot image space"; 919 CHECK_NE(boot_oat_begin, boot_oat_end) << "Can not relocate app image without boot oat file"; 920 const uint32_t boot_image_size = boot_image_end - boot_image_begin; 921 const uint32_t boot_oat_size = boot_oat_end - boot_oat_begin; 922 const uint32_t image_header_boot_image_size = image_header.GetBootImageSize(); 923 const uint32_t image_header_boot_oat_size = image_header.GetBootOatSize(); 924 if (boot_image_size != image_header_boot_image_size) { 925 *error_msg = StringPrintf("Boot image size %" PRIu64 " does not match expected size %" 926 PRIu64, 927 static_cast<uint64_t>(boot_image_size), 928 static_cast<uint64_t>(image_header_boot_image_size)); 929 return false; 930 } 931 if (boot_oat_size != image_header_boot_oat_size) { 932 *error_msg = StringPrintf("Boot oat size %" PRIu64 " does not match expected size %" 933 PRIu64, 934 static_cast<uint64_t>(boot_oat_size), 935 static_cast<uint64_t>(image_header_boot_oat_size)); 936 return false; 937 } 938 TimingLogger logger(__FUNCTION__, true, false); 939 RelocationRange boot_image(image_header.GetBootImageBegin(), 940 boot_image_begin, 941 boot_image_size); 942 RelocationRange boot_oat(image_header.GetBootOatBegin(), 943 boot_oat_begin, 944 boot_oat_size); 945 RelocationRange app_image(reinterpret_cast<uintptr_t>(image_header.GetImageBegin()), 946 reinterpret_cast<uintptr_t>(target_base), 947 image_header.GetImageSize()); 948 // Use the oat data section since this is where the OatFile::Begin is. 949 RelocationRange app_oat(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()), 950 // Not necessarily in low 4GB. 951 reinterpret_cast<uintptr_t>(app_oat_file->Begin()), 952 image_header.GetOatDataEnd() - image_header.GetOatDataBegin()); 953 VLOG(image) << "App image " << app_image; 954 VLOG(image) << "App oat " << app_oat; 955 VLOG(image) << "Boot image " << boot_image; 956 VLOG(image) << "Boot oat " << boot_oat; 957 // True if we need to fixup any heap pointers, otherwise only code pointers. 958 const bool fixup_image = boot_image.Delta() != 0 || app_image.Delta() != 0; 959 const bool fixup_code = boot_oat.Delta() != 0 || app_oat.Delta() != 0; 960 if (!fixup_image && !fixup_code) { 961 // Nothing to fix up. 962 return true; 963 } 964 ScopedDebugDisallowReadBarriers sddrb(Thread::Current()); 965 // Need to update the image to be at the target base. 966 const ImageSection& objects_section = image_header.GetImageSection(ImageHeader::kSectionObjects); 967 uintptr_t objects_begin = reinterpret_cast<uintptr_t>(target_base + objects_section.Offset()); 968 uintptr_t objects_end = reinterpret_cast<uintptr_t>(target_base + objects_section.End()); 969 if (fixup_image) { 970 // Two pass approach, fix up all classes first, then fix up non class-objects. 971 // The visited bitmap is used to ensure that pointer arrays are not forwarded twice. 972 std::unique_ptr<gc::accounting::ContinuousSpaceBitmap> visited_bitmap( 973 gc::accounting::ContinuousSpaceBitmap::Create("Pointer array bitmap", 974 target_base, 975 image_header.GetImageSize())); 976 FixupObjectVisitor fixup_object_visitor(visited_bitmap.get(), 977 boot_image, 978 boot_oat, 979 app_image, 980 app_oat); 981 TimingLogger::ScopedTiming timing("Fixup classes", &logger); 982 // Fixup class only touches app image classes, don't need the mutator lock since the space is 983 // not yet visible to the GC. 984 FixupClassVisitor fixup_class_visitor(boot_image, boot_oat, app_image, app_oat); 985 bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_class_visitor); 986 // Fixup objects may read fields in the boot image, use the mutator lock here for sanity. Though 987 // its probably not required. 988 ScopedObjectAccess soa(Thread::Current()); 989 timing.NewTiming("Fixup objects"); 990 bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_object_visitor); 991 FixupObjectAdapter fixup_adapter(boot_image, boot_oat, app_image, app_oat); 992 // Fixup image roots. 993 CHECK(app_image.InSource(reinterpret_cast<uintptr_t>( 994 image_header.GetImageRoots<kWithoutReadBarrier>()))); 995 image_header.RelocateImageObjects(app_image.Delta()); 996 CHECK_EQ(image_header.GetImageBegin(), target_base); 997 // Fix up dex cache DexFile pointers. 998 auto* dex_caches = image_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)-> 999 AsObjectArray<mirror::DexCache, kVerifyNone, kWithoutReadBarrier>(); 1000 for (int32_t i = 0, count = dex_caches->GetLength(); i < count; ++i) { 1001 mirror::DexCache* dex_cache = dex_caches->Get<kVerifyNone, kWithoutReadBarrier>(i); 1002 // Fix up dex cache pointers. 1003 GcRoot<mirror::String>* strings = dex_cache->GetStrings(); 1004 if (strings != nullptr) { 1005 GcRoot<mirror::String>* new_strings = fixup_adapter.ForwardObject(strings); 1006 if (strings != new_strings) { 1007 dex_cache->SetStrings(new_strings); 1008 } 1009 dex_cache->FixupStrings<kWithoutReadBarrier>(new_strings, fixup_adapter); 1010 } 1011 GcRoot<mirror::Class>* types = dex_cache->GetResolvedTypes(); 1012 if (types != nullptr) { 1013 GcRoot<mirror::Class>* new_types = fixup_adapter.ForwardObject(types); 1014 if (types != new_types) { 1015 dex_cache->SetResolvedTypes(new_types); 1016 } 1017 dex_cache->FixupResolvedTypes<kWithoutReadBarrier>(new_types, fixup_adapter); 1018 } 1019 ArtMethod** methods = dex_cache->GetResolvedMethods(); 1020 if (methods != nullptr) { 1021 ArtMethod** new_methods = fixup_adapter.ForwardObject(methods); 1022 if (methods != new_methods) { 1023 dex_cache->SetResolvedMethods(new_methods); 1024 } 1025 for (size_t j = 0, num = dex_cache->NumResolvedMethods(); j != num; ++j) { 1026 ArtMethod* orig = mirror::DexCache::GetElementPtrSize(new_methods, j, sizeof(void*)); 1027 ArtMethod* copy = fixup_adapter.ForwardObject(orig); 1028 if (orig != copy) { 1029 mirror::DexCache::SetElementPtrSize(new_methods, j, copy, sizeof(void*)); 1030 } 1031 } 1032 } 1033 ArtField** fields = dex_cache->GetResolvedFields(); 1034 if (fields != nullptr) { 1035 ArtField** new_fields = fixup_adapter.ForwardObject(fields); 1036 if (fields != new_fields) { 1037 dex_cache->SetResolvedFields(new_fields); 1038 } 1039 for (size_t j = 0, num = dex_cache->NumResolvedFields(); j != num; ++j) { 1040 ArtField* orig = mirror::DexCache::GetElementPtrSize(new_fields, j, sizeof(void*)); 1041 ArtField* copy = fixup_adapter.ForwardObject(orig); 1042 if (orig != copy) { 1043 mirror::DexCache::SetElementPtrSize(new_fields, j, copy, sizeof(void*)); 1044 } 1045 } 1046 } 1047 } 1048 } 1049 { 1050 // Only touches objects in the app image, no need for mutator lock. 1051 TimingLogger::ScopedTiming timing("Fixup methods", &logger); 1052 FixupArtMethodVisitor method_visitor(fixup_image, boot_image, boot_oat, app_image, app_oat); 1053 image_header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods( 1054 &method_visitor, 1055 target_base, 1056 sizeof(void*)); 1057 } 1058 if (fixup_image) { 1059 { 1060 // Only touches objects in the app image, no need for mutator lock. 1061 TimingLogger::ScopedTiming timing("Fixup fields", &logger); 1062 FixupArtFieldVisitor field_visitor(boot_image, boot_oat, app_image, app_oat); 1063 image_header.GetImageSection(ImageHeader::kSectionArtFields).VisitPackedArtFields( 1064 &field_visitor, 1065 target_base); 1066 } 1067 // In the app image case, the image methods are actually in the boot image. 1068 image_header.RelocateImageMethods(boot_image.Delta()); 1069 const auto& class_table_section = image_header.GetImageSection(ImageHeader::kSectionClassTable); 1070 if (class_table_section.Size() > 0u) { 1071 // Note that we require that ReadFromMemory does not make an internal copy of the elements. 1072 // This also relies on visit roots not doing any verification which could fail after we update 1073 // the roots to be the image addresses. 1074 ScopedObjectAccess soa(Thread::Current()); 1075 WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); 1076 ClassTable temp_table; 1077 temp_table.ReadFromMemory(target_base + class_table_section.Offset()); 1078 FixupRootVisitor root_visitor(boot_image, boot_oat, app_image, app_oat); 1079 temp_table.VisitRoots(root_visitor); 1080 } 1081 } 1082 if (VLOG_IS_ON(image)) { 1083 logger.Dump(LOG(INFO)); 1084 } 1085 return true; 1086} 1087 1088ImageSpace* ImageSpace::Init(const char* image_filename, 1089 const char* image_location, 1090 bool validate_oat_file, 1091 const OatFile* oat_file, 1092 std::string* error_msg) { 1093 CHECK(image_filename != nullptr); 1094 CHECK(image_location != nullptr); 1095 1096 TimingLogger logger(__PRETTY_FUNCTION__, true, VLOG_IS_ON(image)); 1097 VLOG(image) << "ImageSpace::Init entering image_filename=" << image_filename; 1098 1099 std::unique_ptr<File> file; 1100 { 1101 TimingLogger::ScopedTiming timing("OpenImageFile", &logger); 1102 file.reset(OS::OpenFileForReading(image_filename)); 1103 if (file == nullptr) { 1104 *error_msg = StringPrintf("Failed to open '%s'", image_filename); 1105 return nullptr; 1106 } 1107 } 1108 ImageHeader temp_image_header; 1109 ImageHeader* image_header = &temp_image_header; 1110 { 1111 TimingLogger::ScopedTiming timing("ReadImageHeader", &logger); 1112 bool success = file->ReadFully(image_header, sizeof(*image_header)); 1113 if (!success || !image_header->IsValid()) { 1114 *error_msg = StringPrintf("Invalid image header in '%s'", image_filename); 1115 return nullptr; 1116 } 1117 } 1118 // Check that the file is larger or equal to the header size + data size. 1119 const uint64_t image_file_size = static_cast<uint64_t>(file->GetLength()); 1120 if (image_file_size < sizeof(ImageHeader) + image_header->GetDataSize()) { 1121 *error_msg = StringPrintf("Image file truncated: %" PRIu64 " vs. %" PRIu64 ".", 1122 image_file_size, 1123 sizeof(ImageHeader) + image_header->GetDataSize()); 1124 return nullptr; 1125 } 1126 1127 if (oat_file != nullptr) { 1128 // If we have an oat file, check the oat file checksum. The oat file is only non-null for the 1129 // app image case. Otherwise, we open the oat file after the image and check the checksum there. 1130 const uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum(); 1131 const uint32_t image_oat_checksum = image_header->GetOatChecksum(); 1132 if (oat_checksum != image_oat_checksum) { 1133 *error_msg = StringPrintf("Oat checksum 0x%x does not match the image one 0x%x in image %s", 1134 oat_checksum, 1135 image_oat_checksum, 1136 image_filename); 1137 return nullptr; 1138 } 1139 } 1140 1141 if (VLOG_IS_ON(startup)) { 1142 LOG(INFO) << "Dumping image sections"; 1143 for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) { 1144 const auto section_idx = static_cast<ImageHeader::ImageSections>(i); 1145 auto& section = image_header->GetImageSection(section_idx); 1146 LOG(INFO) << section_idx << " start=" 1147 << reinterpret_cast<void*>(image_header->GetImageBegin() + section.Offset()) << " " 1148 << section; 1149 } 1150 } 1151 1152 const auto& bitmap_section = image_header->GetImageSection(ImageHeader::kSectionImageBitmap); 1153 // The location we want to map from is the first aligned page after the end of the stored 1154 // (possibly compressed) data. 1155 const size_t image_bitmap_offset = RoundUp(sizeof(ImageHeader) + image_header->GetDataSize(), 1156 kPageSize); 1157 const size_t end_of_bitmap = image_bitmap_offset + bitmap_section.Size(); 1158 if (end_of_bitmap != image_file_size) { 1159 *error_msg = StringPrintf( 1160 "Image file size does not equal end of bitmap: size=%" PRIu64 " vs. %zu.", image_file_size, 1161 end_of_bitmap); 1162 return nullptr; 1163 } 1164 1165 // The preferred address to map the image, null specifies any address. If we manage to map the 1166 // image at the image begin, the amount of fixup work required is minimized. 1167 std::vector<uint8_t*> addresses(1, image_header->GetImageBegin()); 1168 if (image_header->IsPic()) { 1169 // Can also map at a random low_4gb address since we can relocate in-place. 1170 addresses.push_back(nullptr); 1171 } 1172 1173 // Note: The image header is part of the image due to mmap page alignment required of offset. 1174 std::unique_ptr<MemMap> map; 1175 std::string temp_error_msg; 1176 for (uint8_t* address : addresses) { 1177 TimingLogger::ScopedTiming timing("MapImageFile", &logger); 1178 // Only care about the error message for the last address in addresses. We want to avoid the 1179 // overhead of printing the process maps if we can relocate. 1180 std::string* out_error_msg = (address == addresses.back()) ? &temp_error_msg : nullptr; 1181 const ImageHeader::StorageMode storage_mode = image_header->GetStorageMode(); 1182 if (storage_mode == ImageHeader::kStorageModeUncompressed) { 1183 map.reset(MemMap::MapFileAtAddress(address, 1184 image_header->GetImageSize(), 1185 PROT_READ | PROT_WRITE, 1186 MAP_PRIVATE, 1187 file->Fd(), 1188 0, 1189 /*low_4gb*/true, 1190 /*reuse*/false, 1191 image_filename, 1192 /*out*/out_error_msg)); 1193 } else { 1194 if (storage_mode != ImageHeader::kStorageModeLZ4 && 1195 storage_mode != ImageHeader::kStorageModeLZ4HC) { 1196 *error_msg = StringPrintf("Invalid storage mode in image header %d", 1197 static_cast<int>(storage_mode)); 1198 return nullptr; 1199 } 1200 // Reserve output and decompress into it. 1201 map.reset(MemMap::MapAnonymous(image_location, 1202 address, 1203 image_header->GetImageSize(), 1204 PROT_READ | PROT_WRITE, 1205 /*low_4gb*/true, 1206 /*reuse*/false, 1207 /*out*/out_error_msg)); 1208 if (map != nullptr) { 1209 const size_t stored_size = image_header->GetDataSize(); 1210 const size_t write_offset = sizeof(ImageHeader); // Skip the header. 1211 std::unique_ptr<MemMap> temp_map(MemMap::MapFile(sizeof(ImageHeader) + stored_size, 1212 PROT_READ, 1213 MAP_PRIVATE, 1214 file->Fd(), 1215 /*offset*/0, 1216 /*low_4gb*/false, 1217 image_filename, 1218 out_error_msg)); 1219 if (temp_map == nullptr) { 1220 DCHECK(!out_error_msg->empty()); 1221 return nullptr; 1222 } 1223 memcpy(map->Begin(), image_header, sizeof(ImageHeader)); 1224 const uint64_t start = NanoTime(); 1225 // LZ4HC and LZ4 have same internal format, both use LZ4_decompress. 1226 TimingLogger::ScopedTiming timing2("LZ4 decompress image", &logger); 1227 const size_t decompressed_size = LZ4_decompress_safe( 1228 reinterpret_cast<char*>(temp_map->Begin()) + sizeof(ImageHeader), 1229 reinterpret_cast<char*>(map->Begin()) + write_offset, 1230 stored_size, 1231 map->Size()); 1232 VLOG(image) << "Decompressing image took " << PrettyDuration(NanoTime() - start); 1233 if (decompressed_size + sizeof(ImageHeader) != image_header->GetImageSize()) { 1234 *error_msg = StringPrintf("Decompressed size does not match expected image size %zu vs %zu", 1235 decompressed_size + sizeof(ImageHeader), 1236 image_header->GetImageSize()); 1237 return nullptr; 1238 } 1239 } 1240 } 1241 if (map != nullptr) { 1242 break; 1243 } 1244 } 1245 1246 if (map == nullptr) { 1247 DCHECK(!temp_error_msg.empty()); 1248 *error_msg = temp_error_msg; 1249 return nullptr; 1250 } 1251 DCHECK_EQ(0, memcmp(image_header, map->Begin(), sizeof(ImageHeader))); 1252 1253 std::unique_ptr<MemMap> image_bitmap_map(MemMap::MapFileAtAddress(nullptr, 1254 bitmap_section.Size(), 1255 PROT_READ, MAP_PRIVATE, 1256 file->Fd(), 1257 image_bitmap_offset, 1258 /*low_4gb*/false, 1259 /*reuse*/false, 1260 image_filename, 1261 error_msg)); 1262 if (image_bitmap_map == nullptr) { 1263 *error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str()); 1264 return nullptr; 1265 } 1266 // Loaded the map, use the image header from the file now in case we patch it with 1267 // RelocateInPlace. 1268 image_header = reinterpret_cast<ImageHeader*>(map->Begin()); 1269 const uint32_t bitmap_index = bitmap_index_.FetchAndAddSequentiallyConsistent(1); 1270 std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", 1271 image_filename, 1272 bitmap_index)); 1273 // Bitmap only needs to cover until the end of the mirror objects section. 1274 const ImageSection& image_objects = image_header->GetImageSection(ImageHeader::kSectionObjects); 1275 // We only want the mirror object, not the ArtFields and ArtMethods. 1276 uint8_t* const image_end = map->Begin() + image_objects.End(); 1277 std::unique_ptr<accounting::ContinuousSpaceBitmap> bitmap; 1278 { 1279 TimingLogger::ScopedTiming timing("CreateImageBitmap", &logger); 1280 bitmap.reset( 1281 accounting::ContinuousSpaceBitmap::CreateFromMemMap( 1282 bitmap_name, 1283 image_bitmap_map.release(), 1284 reinterpret_cast<uint8_t*>(map->Begin()), 1285 image_objects.End())); 1286 if (bitmap == nullptr) { 1287 *error_msg = StringPrintf("Could not create bitmap '%s'", bitmap_name.c_str()); 1288 return nullptr; 1289 } 1290 } 1291 { 1292 TimingLogger::ScopedTiming timing("RelocateImage", &logger); 1293 if (!RelocateInPlace(*image_header, 1294 map->Begin(), 1295 bitmap.get(), 1296 oat_file, 1297 error_msg)) { 1298 return nullptr; 1299 } 1300 } 1301 // We only want the mirror object, not the ArtFields and ArtMethods. 1302 std::unique_ptr<ImageSpace> space(new ImageSpace(image_filename, 1303 image_location, 1304 map.release(), 1305 bitmap.release(), 1306 image_end)); 1307 1308 // VerifyImageAllocations() will be called later in Runtime::Init() 1309 // as some class roots like ArtMethod::java_lang_reflect_ArtMethod_ 1310 // and ArtField::java_lang_reflect_ArtField_, which are used from 1311 // Object::SizeOf() which VerifyImageAllocations() calls, are not 1312 // set yet at this point. 1313 if (oat_file == nullptr) { 1314 TimingLogger::ScopedTiming timing("OpenOatFile", &logger); 1315 space->oat_file_.reset(space->OpenOatFile(image_filename, error_msg)); 1316 if (space->oat_file_ == nullptr) { 1317 DCHECK(!error_msg->empty()); 1318 return nullptr; 1319 } 1320 space->oat_file_non_owned_ = space->oat_file_.get(); 1321 } else { 1322 space->oat_file_non_owned_ = oat_file; 1323 } 1324 1325 if (validate_oat_file) { 1326 TimingLogger::ScopedTiming timing("ValidateOatFile", &logger); 1327 if (!space->ValidateOatFile(error_msg)) { 1328 DCHECK(!error_msg->empty()); 1329 return nullptr; 1330 } 1331 } 1332 1333 Runtime* runtime = Runtime::Current(); 1334 1335 // If oat_file is null, then it is the boot image space. Use oat_file_non_owned_ from the space 1336 // to set the runtime methods. 1337 CHECK_EQ(oat_file != nullptr, image_header->IsAppImage()); 1338 if (image_header->IsAppImage()) { 1339 CHECK_EQ(runtime->GetResolutionMethod(), 1340 image_header->GetImageMethod(ImageHeader::kResolutionMethod)); 1341 CHECK_EQ(runtime->GetImtConflictMethod(), 1342 image_header->GetImageMethod(ImageHeader::kImtConflictMethod)); 1343 CHECK_EQ(runtime->GetImtUnimplementedMethod(), 1344 image_header->GetImageMethod(ImageHeader::kImtUnimplementedMethod)); 1345 CHECK_EQ(runtime->GetCalleeSaveMethod(Runtime::kSaveAll), 1346 image_header->GetImageMethod(ImageHeader::kCalleeSaveMethod)); 1347 CHECK_EQ(runtime->GetCalleeSaveMethod(Runtime::kRefsOnly), 1348 image_header->GetImageMethod(ImageHeader::kRefsOnlySaveMethod)); 1349 CHECK_EQ(runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs), 1350 image_header->GetImageMethod(ImageHeader::kRefsAndArgsSaveMethod)); 1351 } else if (!runtime->HasResolutionMethod()) { 1352 runtime->SetInstructionSet(space->oat_file_non_owned_->GetOatHeader().GetInstructionSet()); 1353 runtime->SetResolutionMethod(image_header->GetImageMethod(ImageHeader::kResolutionMethod)); 1354 runtime->SetImtConflictMethod(image_header->GetImageMethod(ImageHeader::kImtConflictMethod)); 1355 runtime->SetImtUnimplementedMethod( 1356 image_header->GetImageMethod(ImageHeader::kImtUnimplementedMethod)); 1357 runtime->SetCalleeSaveMethod( 1358 image_header->GetImageMethod(ImageHeader::kCalleeSaveMethod), Runtime::kSaveAll); 1359 runtime->SetCalleeSaveMethod( 1360 image_header->GetImageMethod(ImageHeader::kRefsOnlySaveMethod), Runtime::kRefsOnly); 1361 runtime->SetCalleeSaveMethod( 1362 image_header->GetImageMethod(ImageHeader::kRefsAndArgsSaveMethod), Runtime::kRefsAndArgs); 1363 } 1364 1365 VLOG(image) << "ImageSpace::Init exiting " << *space.get(); 1366 if (VLOG_IS_ON(image)) { 1367 logger.Dump(LOG(INFO)); 1368 } 1369 return space.release(); 1370} 1371 1372OatFile* ImageSpace::OpenOatFile(const char* image_path, std::string* error_msg) const { 1373 const ImageHeader& image_header = GetImageHeader(); 1374 std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(image_path); 1375 1376 CHECK(image_header.GetOatDataBegin() != nullptr); 1377 1378 OatFile* oat_file = OatFile::Open(oat_filename, 1379 oat_filename, 1380 image_header.GetOatDataBegin(), 1381 image_header.GetOatFileBegin(), 1382 !Runtime::Current()->IsAotCompiler(), 1383 nullptr, 1384 error_msg); 1385 if (oat_file == nullptr) { 1386 *error_msg = StringPrintf("Failed to open oat file '%s' referenced from image %s: %s", 1387 oat_filename.c_str(), GetName(), error_msg->c_str()); 1388 return nullptr; 1389 } 1390 uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum(); 1391 uint32_t image_oat_checksum = image_header.GetOatChecksum(); 1392 if (oat_checksum != image_oat_checksum) { 1393 *error_msg = StringPrintf("Failed to match oat file checksum 0x%x to expected oat checksum 0x%x" 1394 " in image %s", oat_checksum, image_oat_checksum, GetName()); 1395 return nullptr; 1396 } 1397 int32_t image_patch_delta = image_header.GetPatchDelta(); 1398 int32_t oat_patch_delta = oat_file->GetOatHeader().GetImagePatchDelta(); 1399 if (oat_patch_delta != image_patch_delta && !image_header.CompilePic()) { 1400 // We should have already relocated by this point. Bail out. 1401 *error_msg = StringPrintf("Failed to match oat file patch delta %d to expected patch delta %d " 1402 "in image %s", oat_patch_delta, image_patch_delta, GetName()); 1403 return nullptr; 1404 } 1405 1406 return oat_file; 1407} 1408 1409bool ImageSpace::ValidateOatFile(std::string* error_msg) const { 1410 CHECK(oat_file_.get() != nullptr); 1411 for (const OatFile::OatDexFile* oat_dex_file : oat_file_->GetOatDexFiles()) { 1412 const std::string& dex_file_location = oat_dex_file->GetDexFileLocation(); 1413 uint32_t dex_file_location_checksum; 1414 if (!DexFile::GetChecksum(dex_file_location.c_str(), &dex_file_location_checksum, error_msg)) { 1415 *error_msg = StringPrintf("Failed to get checksum of dex file '%s' referenced by image %s: " 1416 "%s", dex_file_location.c_str(), GetName(), error_msg->c_str()); 1417 return false; 1418 } 1419 if (dex_file_location_checksum != oat_dex_file->GetDexFileLocationChecksum()) { 1420 *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file '%s' and " 1421 "dex file '%s' (0x%x != 0x%x)", 1422 oat_file_->GetLocation().c_str(), dex_file_location.c_str(), 1423 oat_dex_file->GetDexFileLocationChecksum(), 1424 dex_file_location_checksum); 1425 return false; 1426 } 1427 } 1428 return true; 1429} 1430 1431const OatFile* ImageSpace::GetOatFile() const { 1432 return oat_file_non_owned_; 1433} 1434 1435std::unique_ptr<const OatFile> ImageSpace::ReleaseOatFile() { 1436 CHECK(oat_file_ != nullptr); 1437 return std::move(oat_file_); 1438} 1439 1440void ImageSpace::Dump(std::ostream& os) const { 1441 os << GetType() 1442 << " begin=" << reinterpret_cast<void*>(Begin()) 1443 << ",end=" << reinterpret_cast<void*>(End()) 1444 << ",size=" << PrettySize(Size()) 1445 << ",name=\"" << GetName() << "\"]"; 1446} 1447 1448void ImageSpace::CreateMultiImageLocations(const std::string& input_image_file_name, 1449 const std::string& boot_classpath, 1450 std::vector<std::string>* image_file_names) { 1451 DCHECK(image_file_names != nullptr); 1452 1453 std::vector<std::string> images; 1454 Split(boot_classpath, ':', &images); 1455 1456 // Add the rest into the list. We have to adjust locations, possibly: 1457 // 1458 // For example, image_file_name is /a/b/c/d/e.art 1459 // images[0] is f/c/d/e.art 1460 // ---------------------------------------------- 1461 // images[1] is g/h/i/j.art -> /a/b/h/i/j.art 1462 const std::string& first_image = images[0]; 1463 // Length of common suffix. 1464 size_t common = 0; 1465 while (common < input_image_file_name.size() && 1466 common < first_image.size() && 1467 *(input_image_file_name.end() - common - 1) == *(first_image.end() - common - 1)) { 1468 ++common; 1469 } 1470 // We want to replace the prefix of the input image with the prefix of the boot class path. 1471 // This handles the case where the image file contains @ separators. 1472 // Example image_file_name is oats/system@framework@boot.art 1473 // images[0] is .../arm/boot.art 1474 // means that the image name prefix will be oats/system@framework@ 1475 // so that the other images are openable. 1476 const size_t old_prefix_length = first_image.size() - common; 1477 const std::string new_prefix = input_image_file_name.substr( 1478 0, 1479 input_image_file_name.size() - common); 1480 1481 // Apply pattern to images[1] .. images[n]. 1482 for (size_t i = 1; i < images.size(); ++i) { 1483 const std::string& image = images[i]; 1484 CHECK_GT(image.length(), old_prefix_length); 1485 std::string suffix = image.substr(old_prefix_length); 1486 image_file_names->push_back(new_prefix + suffix); 1487 } 1488} 1489 1490ImageSpace* ImageSpace::CreateFromAppImage(const char* image, 1491 const OatFile* oat_file, 1492 std::string* error_msg) { 1493 return gc::space::ImageSpace::Init(image, 1494 image, 1495 /*validate_oat_file*/false, 1496 oat_file, 1497 /*out*/error_msg); 1498} 1499 1500} // namespace space 1501} // namespace gc 1502} // namespace art 1503