image_space.cc revision 564289c753cbe3521f9523b350bd713c1fe2fbd4
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 (is_zygote && !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 if (is_zygote) { 448 // Secondary image is out of date. Clear cache and exit to let it retry from scratch. 449 LOG(ERROR) << "Cannot patch secondary image '" << image_location 450 << "', clearing dalvik_cache and restarting zygote."; 451 PruneDalvikCache(image_isa); 452 _exit(1); 453 } else { 454 reason = "Should not have to patch secondary image."; 455 success = false; 456 } 457 } else { 458 // Try to relocate. 459 success = RelocateImage(image_location, cache_filename.c_str(), image_isa, &reason); 460 } 461 462 if (success) { 463 relocated_version_used = true; 464 image_filename = &cache_filename; 465 } else { 466 *error_msg = StringPrintf("Unable to relocate image '%s' from '%s' to '%s': %s", 467 image_location, system_filename.c_str(), 468 cache_filename.c_str(), reason.c_str()); 469 // We failed to create files, remove any possibly garbage output. 470 // Since ImageCreationAllowed was true above, we are the zygote 471 // and therefore the only process expected to generate these for 472 // the device. 473 PruneDalvikCache(image_isa); 474 return nullptr; 475 } 476 } 477 } else { 478 CHECK(has_cache); 479 // We can just use cache's since it should be fine. This might or might not be relocated. 480 image_filename = &cache_filename; 481 } 482 } else { 483 if (has_system && has_cache) { 484 // Check they have the same cksum. If they do use the cache. Otherwise system. 485 if (ChecksumsMatch(system_filename.c_str(), cache_filename.c_str())) { 486 image_filename = &cache_filename; 487 relocated_version_used = true; 488 } else { 489 image_filename = &system_filename; 490 is_system = true; 491 } 492 } else if (has_system) { 493 image_filename = &system_filename; 494 is_system = true; 495 } else { 496 CHECK(has_cache); 497 image_filename = &cache_filename; 498 } 499 } 500 { 501 // Note that we must not use the file descriptor associated with 502 // ScopedFlock::GetFile to Init the image file. We want the file 503 // descriptor (and the associated exclusive lock) to be released when 504 // we leave Create. 505 ScopedFlock image_lock; 506 // Should this be a RDWR lock? This is only a defensive measure, as at 507 // this point the image should exist. 508 // However, only the zygote can write into the global dalvik-cache, so 509 // restrict to zygote processes, or any process that isn't using 510 // /data/dalvik-cache (which we assume to be allowed to write there). 511 const bool rw_lock = is_zygote || !is_global_cache; 512 image_lock.Init(image_filename->c_str(), 513 rw_lock ? (O_CREAT | O_RDWR) : O_RDONLY /* flags */, 514 true /* block */, 515 error_msg); 516 VLOG(startup) << "Using image file " << image_filename->c_str() << " for image location " 517 << image_location; 518 // If we are in /system we can assume the image is good. We can also 519 // assume this if we are using a relocated image (i.e. image checksum 520 // matches) since this is only different by the offset. We need this to 521 // make sure that host tests continue to work. 522 // Since we are the boot image, pass null since we load the oat file from the boot image oat 523 // file name. 524 space = ImageSpace::Init(image_filename->c_str(), 525 image_location, 526 !(is_system || relocated_version_used), 527 /* oat_file */nullptr, 528 error_msg); 529 } 530 if (space != nullptr) { 531 return space; 532 } 533 534 if (relocated_version_used) { 535 // Something is wrong with the relocated copy (even though checksums match). Cleanup. 536 // This can happen if the .oat is corrupt, since the above only checks the .art checksums. 537 // TODO: Check the oat file validity earlier. 538 *error_msg = StringPrintf("Attempted to use relocated version of %s at %s generated from %s " 539 "but image failed to load: %s", 540 image_location, cache_filename.c_str(), system_filename.c_str(), 541 error_msg->c_str()); 542 PruneDalvikCache(image_isa); 543 return nullptr; 544 } else if (is_system) { 545 // If the /system file exists, it should be up-to-date, don't try to generate it. 546 *error_msg = StringPrintf("Failed to load /system image '%s': %s", 547 image_filename->c_str(), error_msg->c_str()); 548 return nullptr; 549 } else { 550 // Otherwise, log a warning and fall through to GenerateImage. 551 LOG(WARNING) << *error_msg; 552 } 553 } 554 555 if (!can_compile) { 556 *error_msg = "Not attempting to compile image because -Xnoimage-dex2oat"; 557 return nullptr; 558 } else if (!dalvik_cache_exists) { 559 *error_msg = StringPrintf("No place to put generated image."); 560 return nullptr; 561 } else if (!ImageCreationAllowed(is_global_cache, error_msg)) { 562 return nullptr; 563 } else if (secondary_image) { 564 *error_msg = "Cannot compile a secondary image."; 565 return nullptr; 566 } else if (!GenerateImage(cache_filename, image_isa, error_msg)) { 567 *error_msg = StringPrintf("Failed to generate image '%s': %s", 568 cache_filename.c_str(), error_msg->c_str()); 569 // We failed to create files, remove any possibly garbage output. 570 // Since ImageCreationAllowed was true above, we are the zygote 571 // and therefore the only process expected to generate these for 572 // the device. 573 PruneDalvikCache(image_isa); 574 return nullptr; 575 } else { 576 // Check whether there is enough space left over after we have generated the image. 577 if (!CheckSpace(cache_filename, error_msg)) { 578 // No. Delete the generated image and try to run out of the dex files. 579 PruneDalvikCache(image_isa); 580 return nullptr; 581 } 582 583 // Note that we must not use the file descriptor associated with 584 // ScopedFlock::GetFile to Init the image file. We want the file 585 // descriptor (and the associated exclusive lock) to be released when 586 // we leave Create. 587 ScopedFlock image_lock; 588 image_lock.Init(cache_filename.c_str(), error_msg); 589 space = ImageSpace::Init(cache_filename.c_str(), image_location, true, nullptr, error_msg); 590 if (space == nullptr) { 591 *error_msg = StringPrintf("Failed to load generated image '%s': %s", 592 cache_filename.c_str(), error_msg->c_str()); 593 } 594 return space; 595 } 596} 597 598void ImageSpace::VerifyImageAllocations() { 599 uint8_t* current = Begin() + RoundUp(sizeof(ImageHeader), kObjectAlignment); 600 while (current < End()) { 601 CHECK_ALIGNED(current, kObjectAlignment); 602 auto* obj = reinterpret_cast<mirror::Object*>(current); 603 CHECK(obj->GetClass() != nullptr) << "Image object at address " << obj << " has null class"; 604 CHECK(live_bitmap_->Test(obj)) << PrettyTypeOf(obj); 605 if (kUseBakerOrBrooksReadBarrier) { 606 obj->AssertReadBarrierPointer(); 607 } 608 current += RoundUp(obj->SizeOf(), kObjectAlignment); 609 } 610} 611 612// Helper class for relocating from one range of memory to another. 613class RelocationRange { 614 public: 615 RelocationRange() = default; 616 RelocationRange(const RelocationRange&) = default; 617 RelocationRange(uintptr_t source, uintptr_t dest, uintptr_t length) 618 : source_(source), 619 dest_(dest), 620 length_(length) {} 621 622 bool InSource(uintptr_t address) const { 623 return address - source_ < length_; 624 } 625 626 bool InDest(uintptr_t address) const { 627 return address - dest_ < length_; 628 } 629 630 // Translate a source address to the destination space. 631 uintptr_t ToDest(uintptr_t address) const { 632 DCHECK(InSource(address)); 633 return address + Delta(); 634 } 635 636 // Returns the delta between the dest from the source. 637 uintptr_t Delta() const { 638 return dest_ - source_; 639 } 640 641 uintptr_t Source() const { 642 return source_; 643 } 644 645 uintptr_t Dest() const { 646 return dest_; 647 } 648 649 uintptr_t Length() const { 650 return length_; 651 } 652 653 private: 654 const uintptr_t source_; 655 const uintptr_t dest_; 656 const uintptr_t length_; 657}; 658 659std::ostream& operator<<(std::ostream& os, const RelocationRange& reloc) { 660 return os << "(" << reinterpret_cast<const void*>(reloc.Source()) << "-" 661 << reinterpret_cast<const void*>(reloc.Source() + reloc.Length()) << ")->(" 662 << reinterpret_cast<const void*>(reloc.Dest()) << "-" 663 << reinterpret_cast<const void*>(reloc.Dest() + reloc.Length()) << ")"; 664} 665 666class FixupVisitor : public ValueObject { 667 public: 668 FixupVisitor(const RelocationRange& boot_image, 669 const RelocationRange& boot_oat, 670 const RelocationRange& app_image, 671 const RelocationRange& app_oat) 672 : boot_image_(boot_image), 673 boot_oat_(boot_oat), 674 app_image_(app_image), 675 app_oat_(app_oat) {} 676 677 // Return the relocated address of a heap object. 678 template <typename T> 679 ALWAYS_INLINE T* ForwardObject(T* src) const { 680 const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src); 681 if (boot_image_.InSource(uint_src)) { 682 return reinterpret_cast<T*>(boot_image_.ToDest(uint_src)); 683 } 684 if (app_image_.InSource(uint_src)) { 685 return reinterpret_cast<T*>(app_image_.ToDest(uint_src)); 686 } 687 // Since we are fixing up the app image, there should only be pointers to the app image and 688 // boot image. 689 DCHECK(src == nullptr) << reinterpret_cast<const void*>(src); 690 return src; 691 } 692 693 // Return the relocated address of a code pointer (contained by an oat file). 694 ALWAYS_INLINE const void* ForwardCode(const void* src) const { 695 const uintptr_t uint_src = reinterpret_cast<uintptr_t>(src); 696 if (boot_oat_.InSource(uint_src)) { 697 return reinterpret_cast<const void*>(boot_oat_.ToDest(uint_src)); 698 } 699 if (app_oat_.InSource(uint_src)) { 700 return reinterpret_cast<const void*>(app_oat_.ToDest(uint_src)); 701 } 702 DCHECK(src == nullptr) << src; 703 return src; 704 } 705 706 // Must be called on pointers that already have been relocated to the destination relocation. 707 ALWAYS_INLINE bool IsInAppImage(mirror::Object* object) const { 708 return app_image_.InDest(reinterpret_cast<uintptr_t>(object)); 709 } 710 711 protected: 712 // Source section. 713 const RelocationRange boot_image_; 714 const RelocationRange boot_oat_; 715 const RelocationRange app_image_; 716 const RelocationRange app_oat_; 717}; 718 719// Adapt for mirror::Class::FixupNativePointers. 720class FixupObjectAdapter : public FixupVisitor { 721 public: 722 template<typename... Args> 723 explicit FixupObjectAdapter(Args... args) : FixupVisitor(args...) {} 724 725 template <typename T> 726 T* operator()(T* obj) const { 727 return ForwardObject(obj); 728 } 729}; 730 731class FixupRootVisitor : public FixupVisitor { 732 public: 733 template<typename... Args> 734 explicit FixupRootVisitor(Args... args) : FixupVisitor(args...) {} 735 736 ALWAYS_INLINE void VisitRootIfNonNull(mirror::CompressedReference<mirror::Object>* root) const 737 SHARED_REQUIRES(Locks::mutator_lock_) { 738 if (!root->IsNull()) { 739 VisitRoot(root); 740 } 741 } 742 743 ALWAYS_INLINE void VisitRoot(mirror::CompressedReference<mirror::Object>* root) const 744 SHARED_REQUIRES(Locks::mutator_lock_) { 745 mirror::Object* ref = root->AsMirrorPtr(); 746 mirror::Object* new_ref = ForwardObject(ref); 747 if (ref != new_ref) { 748 root->Assign(new_ref); 749 } 750 } 751}; 752 753class FixupObjectVisitor : public FixupVisitor { 754 public: 755 template<typename... Args> 756 explicit FixupObjectVisitor(gc::accounting::ContinuousSpaceBitmap* visited, 757 const size_t pointer_size, 758 Args... args) 759 : FixupVisitor(args...), 760 pointer_size_(pointer_size), 761 visited_(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 UpdatePointerArrayContents(mirror::PointerArray* array, const Visitor& visitor) const 790 NO_THREAD_SAFETY_ANALYSIS { 791 DCHECK(array != nullptr); 792 DCHECK(visitor.IsInAppImage(array)); 793 // The bit for the array contents is different than the bit for the array. Since we may have 794 // already visited the array as a long / int array from walking the bitmap without knowing it 795 // was a pointer array. 796 static_assert(kObjectAlignment == 8u, "array bit may be in another object"); 797 mirror::Object* const contents_bit = reinterpret_cast<mirror::Object*>( 798 reinterpret_cast<uintptr_t>(array) + kObjectAlignment); 799 // If the bit is not set then the contents have not yet been updated. 800 if (!visited_->Test(contents_bit)) { 801 array->Fixup<kVerifyNone, kWithoutReadBarrier>(array, pointer_size_, visitor); 802 visited_->Set(contents_bit); 803 } 804 } 805 806 // java.lang.ref.Reference visitor. 807 void operator()(mirror::Class* klass ATTRIBUTE_UNUSED, mirror::Reference* ref) const 808 SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(Locks::heap_bitmap_lock_) { 809 mirror::Object* obj = ref->GetReferent<kWithoutReadBarrier>(); 810 ref->SetFieldObjectWithoutWriteBarrier<false, true, kVerifyNone>( 811 mirror::Reference::ReferentOffset(), 812 ForwardObject(obj)); 813 } 814 815 ALWAYS_INLINE void operator()(mirror::Object* obj) const NO_THREAD_SAFETY_ANALYSIS { 816 if (visited_->Test(obj)) { 817 // Already visited. 818 return; 819 } 820 visited_->Set(obj); 821 822 // Handle class specially first since we need it to be updated to properly visit the rest of 823 // the instance fields. 824 { 825 mirror::Class* klass = obj->GetClass<kVerifyNone, kWithoutReadBarrier>(); 826 DCHECK(klass != nullptr) << "Null class in image"; 827 // No AsClass since our fields aren't quite fixed up yet. 828 mirror::Class* new_klass = down_cast<mirror::Class*>(ForwardObject(klass)); 829 if (klass != new_klass) { 830 obj->SetClass<kVerifyNone>(new_klass); 831 } 832 if (new_klass != klass && IsInAppImage(new_klass)) { 833 // Make sure the klass contents are fixed up since we depend on it to walk the fields. 834 operator()(new_klass); 835 } 836 } 837 838 obj->VisitReferences</*visit native roots*/false, kVerifyNone, kWithoutReadBarrier>( 839 *this, 840 *this); 841 // Note that this code relies on no circular dependencies. 842 // We want to use our own class loader and not the one in the image. 843 if (obj->IsClass<kVerifyNone, kWithoutReadBarrier>()) { 844 mirror::Class* as_klass = obj->AsClass<kVerifyNone, kWithoutReadBarrier>(); 845 FixupObjectAdapter visitor(boot_image_, boot_oat_, app_image_, app_oat_); 846 as_klass->FixupNativePointers<kVerifyNone, kWithoutReadBarrier>(as_klass, 847 pointer_size_, 848 visitor); 849 // Deal with the pointer arrays. Use the helper function since multiple classes can reference 850 // the same arrays. 851 mirror::PointerArray* const vtable = as_klass->GetVTable<kVerifyNone, kWithoutReadBarrier>(); 852 if (vtable != nullptr && IsInAppImage(vtable)) { 853 operator()(vtable); 854 UpdatePointerArrayContents(vtable, visitor); 855 } 856 mirror::IfTable* iftable = as_klass->GetIfTable<kVerifyNone, kWithoutReadBarrier>(); 857 // Ensure iftable arrays are fixed up since we need GetMethodArray to return the valid 858 // contents. 859 if (iftable != nullptr && IsInAppImage(iftable)) { 860 operator()(iftable); 861 for (int32_t i = 0, count = iftable->Count(); i < count; ++i) { 862 if (iftable->GetMethodArrayCount<kVerifyNone, kWithoutReadBarrier>(i) > 0) { 863 mirror::PointerArray* methods = 864 iftable->GetMethodArray<kVerifyNone, kWithoutReadBarrier>(i); 865 if (visitor.IsInAppImage(methods)) { 866 operator()(methods); 867 DCHECK(methods != nullptr); 868 UpdatePointerArrayContents(methods, visitor); 869 } 870 } 871 } 872 } 873 } 874 } 875 876 private: 877 const size_t pointer_size_; 878 gc::accounting::ContinuousSpaceBitmap* const visited_; 879}; 880 881class ForwardObjectAdapter { 882 public: 883 ALWAYS_INLINE ForwardObjectAdapter(const FixupVisitor* visitor) : visitor_(visitor) {} 884 885 template <typename T> 886 ALWAYS_INLINE T* operator()(T* src) const { 887 return visitor_->ForwardObject(src); 888 } 889 890 private: 891 const FixupVisitor* const visitor_; 892}; 893 894class ForwardCodeAdapter { 895 public: 896 ALWAYS_INLINE ForwardCodeAdapter(const FixupVisitor* visitor) 897 : visitor_(visitor) {} 898 899 template <typename T> 900 ALWAYS_INLINE T* operator()(T* src) const { 901 return visitor_->ForwardCode(src); 902 } 903 904 private: 905 const FixupVisitor* const visitor_; 906}; 907 908class FixupArtMethodVisitor : public FixupVisitor, public ArtMethodVisitor { 909 public: 910 template<typename... Args> 911 explicit FixupArtMethodVisitor(bool fixup_heap_objects, size_t pointer_size, Args... args) 912 : FixupVisitor(args...), 913 fixup_heap_objects_(fixup_heap_objects), 914 pointer_size_(pointer_size) {} 915 916 virtual void Visit(ArtMethod* method) NO_THREAD_SAFETY_ANALYSIS { 917 if (fixup_heap_objects_) { 918 method->UpdateObjectsForImageRelocation(ForwardObjectAdapter(this), pointer_size_); 919 } 920 method->UpdateEntrypoints<kWithoutReadBarrier>(ForwardCodeAdapter(this), pointer_size_); 921 } 922 923 private: 924 const bool fixup_heap_objects_; 925 const size_t pointer_size_; 926}; 927 928class FixupArtFieldVisitor : public FixupVisitor, public ArtFieldVisitor { 929 public: 930 template<typename... Args> 931 explicit FixupArtFieldVisitor(Args... args) : FixupVisitor(args...) {} 932 933 virtual void Visit(ArtField* field) NO_THREAD_SAFETY_ANALYSIS { 934 field->UpdateObjects(ForwardObjectAdapter(this)); 935 } 936}; 937 938// Relocate an image space mapped at target_base which possibly used to be at a different base 939// address. Only needs a single image space, not one for both source and destination. 940// In place means modifying a single ImageSpace in place rather than relocating from one ImageSpace 941// to another. 942static bool RelocateInPlace(ImageHeader& image_header, 943 uint8_t* target_base, 944 accounting::ContinuousSpaceBitmap* bitmap, 945 const OatFile* app_oat_file, 946 std::string* error_msg) { 947 DCHECK(error_msg != nullptr); 948 if (!image_header.IsPic()) { 949 if (image_header.GetImageBegin() == target_base) { 950 return true; 951 } 952 *error_msg = StringPrintf("Cannot relocate non-pic image for oat file %s", 953 (app_oat_file != nullptr) ? app_oat_file->GetLocation().c_str() : ""); 954 return false; 955 } 956 // Set up sections. 957 uint32_t boot_image_begin = 0; 958 uint32_t boot_image_end = 0; 959 uint32_t boot_oat_begin = 0; 960 uint32_t boot_oat_end = 0; 961 const size_t pointer_size = image_header.GetPointerSize(); 962 gc::Heap* const heap = Runtime::Current()->GetHeap(); 963 heap->GetBootImagesSize(&boot_image_begin, &boot_image_end, &boot_oat_begin, &boot_oat_end); 964 CHECK_NE(boot_image_begin, boot_image_end) 965 << "Can not relocate app image without boot image space"; 966 CHECK_NE(boot_oat_begin, boot_oat_end) << "Can not relocate app image without boot oat file"; 967 const uint32_t boot_image_size = boot_image_end - boot_image_begin; 968 const uint32_t boot_oat_size = boot_oat_end - boot_oat_begin; 969 const uint32_t image_header_boot_image_size = image_header.GetBootImageSize(); 970 const uint32_t image_header_boot_oat_size = image_header.GetBootOatSize(); 971 if (boot_image_size != image_header_boot_image_size) { 972 *error_msg = StringPrintf("Boot image size %" PRIu64 " does not match expected size %" 973 PRIu64, 974 static_cast<uint64_t>(boot_image_size), 975 static_cast<uint64_t>(image_header_boot_image_size)); 976 return false; 977 } 978 if (boot_oat_size != image_header_boot_oat_size) { 979 *error_msg = StringPrintf("Boot oat size %" PRIu64 " does not match expected size %" 980 PRIu64, 981 static_cast<uint64_t>(boot_oat_size), 982 static_cast<uint64_t>(image_header_boot_oat_size)); 983 return false; 984 } 985 TimingLogger logger(__FUNCTION__, true, false); 986 RelocationRange boot_image(image_header.GetBootImageBegin(), 987 boot_image_begin, 988 boot_image_size); 989 RelocationRange boot_oat(image_header.GetBootOatBegin(), 990 boot_oat_begin, 991 boot_oat_size); 992 RelocationRange app_image(reinterpret_cast<uintptr_t>(image_header.GetImageBegin()), 993 reinterpret_cast<uintptr_t>(target_base), 994 image_header.GetImageSize()); 995 // Use the oat data section since this is where the OatFile::Begin is. 996 RelocationRange app_oat(reinterpret_cast<uintptr_t>(image_header.GetOatDataBegin()), 997 // Not necessarily in low 4GB. 998 reinterpret_cast<uintptr_t>(app_oat_file->Begin()), 999 image_header.GetOatDataEnd() - image_header.GetOatDataBegin()); 1000 VLOG(image) << "App image " << app_image; 1001 VLOG(image) << "App oat " << app_oat; 1002 VLOG(image) << "Boot image " << boot_image; 1003 VLOG(image) << "Boot oat " << boot_oat; 1004 // True if we need to fixup any heap pointers, otherwise only code pointers. 1005 const bool fixup_image = boot_image.Delta() != 0 || app_image.Delta() != 0; 1006 const bool fixup_code = boot_oat.Delta() != 0 || app_oat.Delta() != 0; 1007 if (!fixup_image && !fixup_code) { 1008 // Nothing to fix up. 1009 return true; 1010 } 1011 ScopedDebugDisallowReadBarriers sddrb(Thread::Current()); 1012 // Need to update the image to be at the target base. 1013 const ImageSection& objects_section = image_header.GetImageSection(ImageHeader::kSectionObjects); 1014 uintptr_t objects_begin = reinterpret_cast<uintptr_t>(target_base + objects_section.Offset()); 1015 uintptr_t objects_end = reinterpret_cast<uintptr_t>(target_base + objects_section.End()); 1016 if (fixup_image) { 1017 // Two pass approach, fix up all classes first, then fix up non class-objects. 1018 // The visited bitmap is used to ensure that pointer arrays are not forwarded twice. 1019 std::unique_ptr<gc::accounting::ContinuousSpaceBitmap> visited_bitmap( 1020 gc::accounting::ContinuousSpaceBitmap::Create("Relocate bitmap", 1021 target_base, 1022 image_header.GetImageSize())); 1023 FixupObjectVisitor fixup_object_visitor(visited_bitmap.get(), 1024 pointer_size, 1025 boot_image, 1026 boot_oat, 1027 app_image, 1028 app_oat); 1029 TimingLogger::ScopedTiming timing("Fixup classes", &logger); 1030 // Fixup objects may read fields in the boot image, use the mutator lock here for sanity. Though 1031 // its probably not required. 1032 ScopedObjectAccess soa(Thread::Current()); 1033 timing.NewTiming("Fixup objects"); 1034 bitmap->VisitMarkedRange(objects_begin, objects_end, fixup_object_visitor); 1035 FixupObjectAdapter fixup_adapter(boot_image, boot_oat, app_image, app_oat); 1036 // Fixup image roots. 1037 CHECK(app_image.InSource(reinterpret_cast<uintptr_t>( 1038 image_header.GetImageRoots<kWithoutReadBarrier>()))); 1039 image_header.RelocateImageObjects(app_image.Delta()); 1040 CHECK_EQ(image_header.GetImageBegin(), target_base); 1041 // Fix up dex cache DexFile pointers. 1042 auto* dex_caches = image_header.GetImageRoot<kWithoutReadBarrier>(ImageHeader::kDexCaches)-> 1043 AsObjectArray<mirror::DexCache, kVerifyNone, kWithoutReadBarrier>(); 1044 for (int32_t i = 0, count = dex_caches->GetLength(); i < count; ++i) { 1045 mirror::DexCache* dex_cache = dex_caches->Get<kVerifyNone, kWithoutReadBarrier>(i); 1046 // Fix up dex cache pointers. 1047 GcRoot<mirror::String>* strings = dex_cache->GetStrings(); 1048 if (strings != nullptr) { 1049 GcRoot<mirror::String>* new_strings = fixup_adapter.ForwardObject(strings); 1050 if (strings != new_strings) { 1051 dex_cache->SetStrings(new_strings); 1052 } 1053 dex_cache->FixupStrings<kWithoutReadBarrier>(new_strings, fixup_adapter); 1054 } 1055 GcRoot<mirror::Class>* types = dex_cache->GetResolvedTypes(); 1056 if (types != nullptr) { 1057 GcRoot<mirror::Class>* new_types = fixup_adapter.ForwardObject(types); 1058 if (types != new_types) { 1059 dex_cache->SetResolvedTypes(new_types); 1060 } 1061 dex_cache->FixupResolvedTypes<kWithoutReadBarrier>(new_types, fixup_adapter); 1062 } 1063 ArtMethod** methods = dex_cache->GetResolvedMethods(); 1064 if (methods != nullptr) { 1065 ArtMethod** new_methods = fixup_adapter.ForwardObject(methods); 1066 if (methods != new_methods) { 1067 dex_cache->SetResolvedMethods(new_methods); 1068 } 1069 for (size_t j = 0, num = dex_cache->NumResolvedMethods(); j != num; ++j) { 1070 ArtMethod* orig = mirror::DexCache::GetElementPtrSize(new_methods, j, pointer_size); 1071 ArtMethod* copy = fixup_adapter.ForwardObject(orig); 1072 if (orig != copy) { 1073 mirror::DexCache::SetElementPtrSize(new_methods, j, copy, pointer_size); 1074 } 1075 } 1076 } 1077 ArtField** fields = dex_cache->GetResolvedFields(); 1078 if (fields != nullptr) { 1079 ArtField** new_fields = fixup_adapter.ForwardObject(fields); 1080 if (fields != new_fields) { 1081 dex_cache->SetResolvedFields(new_fields); 1082 } 1083 for (size_t j = 0, num = dex_cache->NumResolvedFields(); j != num; ++j) { 1084 ArtField* orig = mirror::DexCache::GetElementPtrSize(new_fields, j, pointer_size); 1085 ArtField* copy = fixup_adapter.ForwardObject(orig); 1086 if (orig != copy) { 1087 mirror::DexCache::SetElementPtrSize(new_fields, j, copy, pointer_size); 1088 } 1089 } 1090 } 1091 } 1092 } 1093 { 1094 // Only touches objects in the app image, no need for mutator lock. 1095 TimingLogger::ScopedTiming timing("Fixup methods", &logger); 1096 FixupArtMethodVisitor method_visitor(fixup_image, 1097 pointer_size, 1098 boot_image, 1099 boot_oat, 1100 app_image, 1101 app_oat); 1102 image_header.GetImageSection(ImageHeader::kSectionArtMethods).VisitPackedArtMethods( 1103 &method_visitor, 1104 target_base, 1105 pointer_size); 1106 } 1107 if (fixup_image) { 1108 { 1109 // Only touches objects in the app image, no need for mutator lock. 1110 TimingLogger::ScopedTiming timing("Fixup fields", &logger); 1111 FixupArtFieldVisitor field_visitor(boot_image, boot_oat, app_image, app_oat); 1112 image_header.GetImageSection(ImageHeader::kSectionArtFields).VisitPackedArtFields( 1113 &field_visitor, 1114 target_base); 1115 } 1116 // In the app image case, the image methods are actually in the boot image. 1117 image_header.RelocateImageMethods(boot_image.Delta()); 1118 const auto& class_table_section = image_header.GetImageSection(ImageHeader::kSectionClassTable); 1119 if (class_table_section.Size() > 0u) { 1120 // Note that we require that ReadFromMemory does not make an internal copy of the elements. 1121 // This also relies on visit roots not doing any verification which could fail after we update 1122 // the roots to be the image addresses. 1123 ScopedObjectAccess soa(Thread::Current()); 1124 WriterMutexLock mu(Thread::Current(), *Locks::classlinker_classes_lock_); 1125 ClassTable temp_table; 1126 temp_table.ReadFromMemory(target_base + class_table_section.Offset()); 1127 FixupRootVisitor root_visitor(boot_image, boot_oat, app_image, app_oat); 1128 temp_table.VisitRoots(root_visitor); 1129 } 1130 } 1131 if (VLOG_IS_ON(image)) { 1132 logger.Dump(LOG(INFO)); 1133 } 1134 return true; 1135} 1136 1137ImageSpace* ImageSpace::Init(const char* image_filename, 1138 const char* image_location, 1139 bool validate_oat_file, 1140 const OatFile* oat_file, 1141 std::string* error_msg) { 1142 CHECK(image_filename != nullptr); 1143 CHECK(image_location != nullptr); 1144 1145 TimingLogger logger(__PRETTY_FUNCTION__, true, VLOG_IS_ON(image)); 1146 VLOG(image) << "ImageSpace::Init entering image_filename=" << image_filename; 1147 1148 std::unique_ptr<File> file; 1149 { 1150 TimingLogger::ScopedTiming timing("OpenImageFile", &logger); 1151 file.reset(OS::OpenFileForReading(image_filename)); 1152 if (file == nullptr) { 1153 *error_msg = StringPrintf("Failed to open '%s'", image_filename); 1154 return nullptr; 1155 } 1156 } 1157 ImageHeader temp_image_header; 1158 ImageHeader* image_header = &temp_image_header; 1159 { 1160 TimingLogger::ScopedTiming timing("ReadImageHeader", &logger); 1161 bool success = file->ReadFully(image_header, sizeof(*image_header)); 1162 if (!success || !image_header->IsValid()) { 1163 *error_msg = StringPrintf("Invalid image header in '%s'", image_filename); 1164 return nullptr; 1165 } 1166 } 1167 // Check that the file is larger or equal to the header size + data size. 1168 const uint64_t image_file_size = static_cast<uint64_t>(file->GetLength()); 1169 if (image_file_size < sizeof(ImageHeader) + image_header->GetDataSize()) { 1170 *error_msg = StringPrintf("Image file truncated: %" PRIu64 " vs. %" PRIu64 ".", 1171 image_file_size, 1172 sizeof(ImageHeader) + image_header->GetDataSize()); 1173 return nullptr; 1174 } 1175 1176 if (oat_file != nullptr) { 1177 // If we have an oat file, check the oat file checksum. The oat file is only non-null for the 1178 // app image case. Otherwise, we open the oat file after the image and check the checksum there. 1179 const uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum(); 1180 const uint32_t image_oat_checksum = image_header->GetOatChecksum(); 1181 if (oat_checksum != image_oat_checksum) { 1182 *error_msg = StringPrintf("Oat checksum 0x%x does not match the image one 0x%x in image %s", 1183 oat_checksum, 1184 image_oat_checksum, 1185 image_filename); 1186 return nullptr; 1187 } 1188 } 1189 1190 if (VLOG_IS_ON(startup)) { 1191 LOG(INFO) << "Dumping image sections"; 1192 for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) { 1193 const auto section_idx = static_cast<ImageHeader::ImageSections>(i); 1194 auto& section = image_header->GetImageSection(section_idx); 1195 LOG(INFO) << section_idx << " start=" 1196 << reinterpret_cast<void*>(image_header->GetImageBegin() + section.Offset()) << " " 1197 << section; 1198 } 1199 } 1200 1201 const auto& bitmap_section = image_header->GetImageSection(ImageHeader::kSectionImageBitmap); 1202 // The location we want to map from is the first aligned page after the end of the stored 1203 // (possibly compressed) data. 1204 const size_t image_bitmap_offset = RoundUp(sizeof(ImageHeader) + image_header->GetDataSize(), 1205 kPageSize); 1206 const size_t end_of_bitmap = image_bitmap_offset + bitmap_section.Size(); 1207 if (end_of_bitmap != image_file_size) { 1208 *error_msg = StringPrintf( 1209 "Image file size does not equal end of bitmap: size=%" PRIu64 " vs. %zu.", image_file_size, 1210 end_of_bitmap); 1211 return nullptr; 1212 } 1213 1214 // The preferred address to map the image, null specifies any address. If we manage to map the 1215 // image at the image begin, the amount of fixup work required is minimized. 1216 std::vector<uint8_t*> addresses(1, image_header->GetImageBegin()); 1217 if (image_header->IsPic()) { 1218 // Can also map at a random low_4gb address since we can relocate in-place. 1219 addresses.push_back(nullptr); 1220 } 1221 1222 // Note: The image header is part of the image due to mmap page alignment required of offset. 1223 std::unique_ptr<MemMap> map; 1224 std::string temp_error_msg; 1225 for (uint8_t* address : addresses) { 1226 TimingLogger::ScopedTiming timing("MapImageFile", &logger); 1227 // Only care about the error message for the last address in addresses. We want to avoid the 1228 // overhead of printing the process maps if we can relocate. 1229 std::string* out_error_msg = (address == addresses.back()) ? &temp_error_msg : nullptr; 1230 const ImageHeader::StorageMode storage_mode = image_header->GetStorageMode(); 1231 if (storage_mode == ImageHeader::kStorageModeUncompressed) { 1232 map.reset(MemMap::MapFileAtAddress(address, 1233 image_header->GetImageSize(), 1234 PROT_READ | PROT_WRITE, 1235 MAP_PRIVATE, 1236 file->Fd(), 1237 0, 1238 /*low_4gb*/true, 1239 /*reuse*/false, 1240 image_filename, 1241 /*out*/out_error_msg)); 1242 } else { 1243 if (storage_mode != ImageHeader::kStorageModeLZ4 && 1244 storage_mode != ImageHeader::kStorageModeLZ4HC) { 1245 *error_msg = StringPrintf("Invalid storage mode in image header %d", 1246 static_cast<int>(storage_mode)); 1247 return nullptr; 1248 } 1249 // Reserve output and decompress into it. 1250 map.reset(MemMap::MapAnonymous(image_location, 1251 address, 1252 image_header->GetImageSize(), 1253 PROT_READ | PROT_WRITE, 1254 /*low_4gb*/true, 1255 /*reuse*/false, 1256 /*out*/out_error_msg)); 1257 if (map != nullptr) { 1258 const size_t stored_size = image_header->GetDataSize(); 1259 const size_t decompress_offset = sizeof(ImageHeader); // Skip the header. 1260 std::unique_ptr<MemMap> temp_map(MemMap::MapFile(sizeof(ImageHeader) + stored_size, 1261 PROT_READ, 1262 MAP_PRIVATE, 1263 file->Fd(), 1264 /*offset*/0, 1265 /*low_4gb*/false, 1266 image_filename, 1267 out_error_msg)); 1268 if (temp_map == nullptr) { 1269 DCHECK(!out_error_msg->empty()); 1270 return nullptr; 1271 } 1272 memcpy(map->Begin(), image_header, sizeof(ImageHeader)); 1273 const uint64_t start = NanoTime(); 1274 // LZ4HC and LZ4 have same internal format, both use LZ4_decompress. 1275 TimingLogger::ScopedTiming timing2("LZ4 decompress image", &logger); 1276 const size_t decompressed_size = LZ4_decompress_safe( 1277 reinterpret_cast<char*>(temp_map->Begin()) + sizeof(ImageHeader), 1278 reinterpret_cast<char*>(map->Begin()) + decompress_offset, 1279 stored_size, 1280 map->Size() - decompress_offset); 1281 VLOG(image) << "Decompressing image took " << PrettyDuration(NanoTime() - start); 1282 if (decompressed_size + sizeof(ImageHeader) != image_header->GetImageSize()) { 1283 *error_msg = StringPrintf( 1284 "Decompressed size does not match expected image size %zu vs %zu", 1285 decompressed_size + sizeof(ImageHeader), 1286 image_header->GetImageSize()); 1287 return nullptr; 1288 } 1289 } 1290 } 1291 if (map != nullptr) { 1292 break; 1293 } 1294 } 1295 1296 if (map == nullptr) { 1297 DCHECK(!temp_error_msg.empty()); 1298 *error_msg = temp_error_msg; 1299 return nullptr; 1300 } 1301 DCHECK_EQ(0, memcmp(image_header, map->Begin(), sizeof(ImageHeader))); 1302 1303 std::unique_ptr<MemMap> image_bitmap_map(MemMap::MapFileAtAddress(nullptr, 1304 bitmap_section.Size(), 1305 PROT_READ, MAP_PRIVATE, 1306 file->Fd(), 1307 image_bitmap_offset, 1308 /*low_4gb*/false, 1309 /*reuse*/false, 1310 image_filename, 1311 error_msg)); 1312 if (image_bitmap_map == nullptr) { 1313 *error_msg = StringPrintf("Failed to map image bitmap: %s", error_msg->c_str()); 1314 return nullptr; 1315 } 1316 // Loaded the map, use the image header from the file now in case we patch it with 1317 // RelocateInPlace. 1318 image_header = reinterpret_cast<ImageHeader*>(map->Begin()); 1319 const uint32_t bitmap_index = bitmap_index_.FetchAndAddSequentiallyConsistent(1); 1320 std::string bitmap_name(StringPrintf("imagespace %s live-bitmap %u", 1321 image_filename, 1322 bitmap_index)); 1323 // Bitmap only needs to cover until the end of the mirror objects section. 1324 const ImageSection& image_objects = image_header->GetImageSection(ImageHeader::kSectionObjects); 1325 // We only want the mirror object, not the ArtFields and ArtMethods. 1326 uint8_t* const image_end = map->Begin() + image_objects.End(); 1327 std::unique_ptr<accounting::ContinuousSpaceBitmap> bitmap; 1328 { 1329 TimingLogger::ScopedTiming timing("CreateImageBitmap", &logger); 1330 bitmap.reset( 1331 accounting::ContinuousSpaceBitmap::CreateFromMemMap( 1332 bitmap_name, 1333 image_bitmap_map.release(), 1334 reinterpret_cast<uint8_t*>(map->Begin()), 1335 image_objects.End())); 1336 if (bitmap == nullptr) { 1337 *error_msg = StringPrintf("Could not create bitmap '%s'", bitmap_name.c_str()); 1338 return nullptr; 1339 } 1340 } 1341 { 1342 TimingLogger::ScopedTiming timing("RelocateImage", &logger); 1343 if (!RelocateInPlace(*image_header, 1344 map->Begin(), 1345 bitmap.get(), 1346 oat_file, 1347 error_msg)) { 1348 return nullptr; 1349 } 1350 } 1351 // We only want the mirror object, not the ArtFields and ArtMethods. 1352 std::unique_ptr<ImageSpace> space(new ImageSpace(image_filename, 1353 image_location, 1354 map.release(), 1355 bitmap.release(), 1356 image_end)); 1357 1358 // VerifyImageAllocations() will be called later in Runtime::Init() 1359 // as some class roots like ArtMethod::java_lang_reflect_ArtMethod_ 1360 // and ArtField::java_lang_reflect_ArtField_, which are used from 1361 // Object::SizeOf() which VerifyImageAllocations() calls, are not 1362 // set yet at this point. 1363 if (oat_file == nullptr) { 1364 TimingLogger::ScopedTiming timing("OpenOatFile", &logger); 1365 space->oat_file_.reset(space->OpenOatFile(image_filename, error_msg)); 1366 if (space->oat_file_ == nullptr) { 1367 DCHECK(!error_msg->empty()); 1368 return nullptr; 1369 } 1370 space->oat_file_non_owned_ = space->oat_file_.get(); 1371 } else { 1372 space->oat_file_non_owned_ = oat_file; 1373 } 1374 1375 if (validate_oat_file) { 1376 TimingLogger::ScopedTiming timing("ValidateOatFile", &logger); 1377 if (!space->ValidateOatFile(error_msg)) { 1378 DCHECK(!error_msg->empty()); 1379 return nullptr; 1380 } 1381 } 1382 1383 Runtime* runtime = Runtime::Current(); 1384 1385 // If oat_file is null, then it is the boot image space. Use oat_file_non_owned_ from the space 1386 // to set the runtime methods. 1387 CHECK_EQ(oat_file != nullptr, image_header->IsAppImage()); 1388 if (image_header->IsAppImage()) { 1389 CHECK_EQ(runtime->GetResolutionMethod(), 1390 image_header->GetImageMethod(ImageHeader::kResolutionMethod)); 1391 CHECK_EQ(runtime->GetImtConflictMethod(), 1392 image_header->GetImageMethod(ImageHeader::kImtConflictMethod)); 1393 CHECK_EQ(runtime->GetImtUnimplementedMethod(), 1394 image_header->GetImageMethod(ImageHeader::kImtUnimplementedMethod)); 1395 CHECK_EQ(runtime->GetCalleeSaveMethod(Runtime::kSaveAll), 1396 image_header->GetImageMethod(ImageHeader::kCalleeSaveMethod)); 1397 CHECK_EQ(runtime->GetCalleeSaveMethod(Runtime::kRefsOnly), 1398 image_header->GetImageMethod(ImageHeader::kRefsOnlySaveMethod)); 1399 CHECK_EQ(runtime->GetCalleeSaveMethod(Runtime::kRefsAndArgs), 1400 image_header->GetImageMethod(ImageHeader::kRefsAndArgsSaveMethod)); 1401 } else if (!runtime->HasResolutionMethod()) { 1402 runtime->SetInstructionSet(space->oat_file_non_owned_->GetOatHeader().GetInstructionSet()); 1403 runtime->SetResolutionMethod(image_header->GetImageMethod(ImageHeader::kResolutionMethod)); 1404 runtime->SetImtConflictMethod(image_header->GetImageMethod(ImageHeader::kImtConflictMethod)); 1405 runtime->SetImtUnimplementedMethod( 1406 image_header->GetImageMethod(ImageHeader::kImtUnimplementedMethod)); 1407 runtime->SetCalleeSaveMethod( 1408 image_header->GetImageMethod(ImageHeader::kCalleeSaveMethod), Runtime::kSaveAll); 1409 runtime->SetCalleeSaveMethod( 1410 image_header->GetImageMethod(ImageHeader::kRefsOnlySaveMethod), Runtime::kRefsOnly); 1411 runtime->SetCalleeSaveMethod( 1412 image_header->GetImageMethod(ImageHeader::kRefsAndArgsSaveMethod), Runtime::kRefsAndArgs); 1413 } 1414 1415 VLOG(image) << "ImageSpace::Init exiting " << *space.get(); 1416 if (VLOG_IS_ON(image)) { 1417 logger.Dump(LOG(INFO)); 1418 } 1419 return space.release(); 1420} 1421 1422OatFile* ImageSpace::OpenOatFile(const char* image_path, std::string* error_msg) const { 1423 const ImageHeader& image_header = GetImageHeader(); 1424 std::string oat_filename = ImageHeader::GetOatLocationFromImageLocation(image_path); 1425 1426 CHECK(image_header.GetOatDataBegin() != nullptr); 1427 1428 OatFile* oat_file = OatFile::Open(oat_filename, 1429 oat_filename, 1430 image_header.GetOatDataBegin(), 1431 image_header.GetOatFileBegin(), 1432 !Runtime::Current()->IsAotCompiler(), 1433 /*low_4gb*/false, 1434 nullptr, 1435 error_msg); 1436 if (oat_file == nullptr) { 1437 *error_msg = StringPrintf("Failed to open oat file '%s' referenced from image %s: %s", 1438 oat_filename.c_str(), GetName(), error_msg->c_str()); 1439 return nullptr; 1440 } 1441 uint32_t oat_checksum = oat_file->GetOatHeader().GetChecksum(); 1442 uint32_t image_oat_checksum = image_header.GetOatChecksum(); 1443 if (oat_checksum != image_oat_checksum) { 1444 *error_msg = StringPrintf("Failed to match oat file checksum 0x%x to expected oat checksum 0x%x" 1445 " in image %s", oat_checksum, image_oat_checksum, GetName()); 1446 return nullptr; 1447 } 1448 int32_t image_patch_delta = image_header.GetPatchDelta(); 1449 int32_t oat_patch_delta = oat_file->GetOatHeader().GetImagePatchDelta(); 1450 if (oat_patch_delta != image_patch_delta && !image_header.CompilePic()) { 1451 // We should have already relocated by this point. Bail out. 1452 *error_msg = StringPrintf("Failed to match oat file patch delta %d to expected patch delta %d " 1453 "in image %s", oat_patch_delta, image_patch_delta, GetName()); 1454 return nullptr; 1455 } 1456 1457 return oat_file; 1458} 1459 1460bool ImageSpace::ValidateOatFile(std::string* error_msg) const { 1461 CHECK(oat_file_.get() != nullptr); 1462 for (const OatFile::OatDexFile* oat_dex_file : oat_file_->GetOatDexFiles()) { 1463 const std::string& dex_file_location = oat_dex_file->GetDexFileLocation(); 1464 uint32_t dex_file_location_checksum; 1465 if (!DexFile::GetChecksum(dex_file_location.c_str(), &dex_file_location_checksum, error_msg)) { 1466 *error_msg = StringPrintf("Failed to get checksum of dex file '%s' referenced by image %s: " 1467 "%s", dex_file_location.c_str(), GetName(), error_msg->c_str()); 1468 return false; 1469 } 1470 if (dex_file_location_checksum != oat_dex_file->GetDexFileLocationChecksum()) { 1471 *error_msg = StringPrintf("ValidateOatFile found checksum mismatch between oat file '%s' and " 1472 "dex file '%s' (0x%x != 0x%x)", 1473 oat_file_->GetLocation().c_str(), dex_file_location.c_str(), 1474 oat_dex_file->GetDexFileLocationChecksum(), 1475 dex_file_location_checksum); 1476 return false; 1477 } 1478 } 1479 return true; 1480} 1481 1482const OatFile* ImageSpace::GetOatFile() const { 1483 return oat_file_non_owned_; 1484} 1485 1486std::unique_ptr<const OatFile> ImageSpace::ReleaseOatFile() { 1487 CHECK(oat_file_ != nullptr); 1488 return std::move(oat_file_); 1489} 1490 1491void ImageSpace::Dump(std::ostream& os) const { 1492 os << GetType() 1493 << " begin=" << reinterpret_cast<void*>(Begin()) 1494 << ",end=" << reinterpret_cast<void*>(End()) 1495 << ",size=" << PrettySize(Size()) 1496 << ",name=\"" << GetName() << "\"]"; 1497} 1498 1499void ImageSpace::CreateMultiImageLocations(const std::string& input_image_file_name, 1500 const std::string& boot_classpath, 1501 std::vector<std::string>* image_file_names) { 1502 DCHECK(image_file_names != nullptr); 1503 1504 std::vector<std::string> images; 1505 Split(boot_classpath, ':', &images); 1506 1507 // Add the rest into the list. We have to adjust locations, possibly: 1508 // 1509 // For example, image_file_name is /a/b/c/d/e.art 1510 // images[0] is f/c/d/e.art 1511 // ---------------------------------------------- 1512 // images[1] is g/h/i/j.art -> /a/b/h/i/j.art 1513 const std::string& first_image = images[0]; 1514 // Length of common suffix. 1515 size_t common = 0; 1516 while (common < input_image_file_name.size() && 1517 common < first_image.size() && 1518 *(input_image_file_name.end() - common - 1) == *(first_image.end() - common - 1)) { 1519 ++common; 1520 } 1521 // We want to replace the prefix of the input image with the prefix of the boot class path. 1522 // This handles the case where the image file contains @ separators. 1523 // Example image_file_name is oats/system@framework@boot.art 1524 // images[0] is .../arm/boot.art 1525 // means that the image name prefix will be oats/system@framework@ 1526 // so that the other images are openable. 1527 const size_t old_prefix_length = first_image.size() - common; 1528 const std::string new_prefix = input_image_file_name.substr( 1529 0, 1530 input_image_file_name.size() - common); 1531 1532 // Apply pattern to images[1] .. images[n]. 1533 for (size_t i = 1; i < images.size(); ++i) { 1534 const std::string& image = images[i]; 1535 CHECK_GT(image.length(), old_prefix_length); 1536 std::string suffix = image.substr(old_prefix_length); 1537 image_file_names->push_back(new_prefix + suffix); 1538 } 1539} 1540 1541ImageSpace* ImageSpace::CreateFromAppImage(const char* image, 1542 const OatFile* oat_file, 1543 std::string* error_msg) { 1544 return gc::space::ImageSpace::Init(image, 1545 image, 1546 /*validate_oat_file*/false, 1547 oat_file, 1548 /*out*/error_msg); 1549} 1550 1551void ImageSpace::DumpSections(std::ostream& os) const { 1552 const uint8_t* base = Begin(); 1553 const ImageHeader& header = GetImageHeader(); 1554 for (size_t i = 0; i < ImageHeader::kSectionCount; ++i) { 1555 auto section_type = static_cast<ImageHeader::ImageSections>(i); 1556 const ImageSection& section = header.GetImageSection(section_type); 1557 os << section_type << " " << reinterpret_cast<const void*>(base + section.Offset()) 1558 << "-" << reinterpret_cast<const void*>(base + section.End()) << "\n"; 1559 } 1560} 1561 1562} // namespace space 1563} // namespace gc 1564} // namespace art 1565