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