diff options
| -rw-r--r-- | runtime/class_linker.cc | 67 | ||||
| -rw-r--r-- | runtime/class_linker.h | 7 | ||||
| -rw-r--r-- | runtime/runtime.cc | 13 |
3 files changed, 67 insertions, 20 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index dde100125a..d5a5ea6797 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -322,7 +322,8 @@ ClassLinker::ClassLinker(InternTable* intern_table) std::fill_n(find_array_class_cache_, kFindArrayCacheSize, GcRoot<mirror::Class>(nullptr)); } -void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> boot_class_path) { +bool ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> boot_class_path, + std::string* error_msg) { VLOG(startup) << "ClassLinker::Init"; Thread* const self = Thread::Current(); @@ -477,9 +478,15 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b // Setup boot_class_path_ and register class_path now that we can use AllocObjectArray to create // DexCache instances. Needs to be after String, Field, Method arrays since AllocDexCache uses // these roots. - CHECK_NE(0U, boot_class_path.size()); + if (boot_class_path.empty()) { + *error_msg = "Boot classpath is empty."; + return false; + } for (auto& dex_file : boot_class_path) { - CHECK(dex_file.get() != nullptr); + if (dex_file.get() == nullptr) { + *error_msg = "Null dex file."; + return false; + } AppendToBootClassPath(self, *dex_file); opened_dex_files_.push_back(std::move(dex_file)); } @@ -660,6 +667,8 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b FinishInit(self); VLOG(startup) << "ClassLinker::InitFromCompiler exiting"; + + return true; } void ClassLinker::FinishInit(Thread* self) { @@ -850,7 +859,7 @@ class SetInterpreterEntrypointArtMethodVisitor : public ArtMethodVisitor { DISALLOW_COPY_AND_ASSIGN(SetInterpreterEntrypointArtMethodVisitor); }; -void ClassLinker::InitFromImage() { +bool ClassLinker::InitFromImage(std::string* error_msg) { VLOG(startup) << "ClassLinker::InitFromImage entering"; CHECK(!init_done_); @@ -895,22 +904,32 @@ void ClassLinker::InitFromImage() { java_lang_Object->GetObjectSize(), VoidFunctor())); - CHECK_EQ(oat_file->GetOatHeader().GetDexFileCount(), - static_cast<uint32_t>(dex_caches->GetLength())); + if (oat_file->GetOatHeader().GetDexFileCount() != + static_cast<uint32_t>(dex_caches->GetLength())) { + *error_msg = "Dex cache count and dex file count mismatch while trying to initialize from " + "image"; + return false; + } for (int32_t i = 0; i < dex_caches->GetLength(); i++) { StackHandleScope<1> hs2(self); Handle<mirror::DexCache> dex_cache(hs2.NewHandle(dex_caches->Get(i))); const std::string& dex_file_location(dex_cache->GetLocation()->ToModifiedUtf8()); const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file_location.c_str(), nullptr); - CHECK(oat_dex_file != nullptr) << oat_file->GetLocation() << " " << dex_file_location; - std::string error_msg; - std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&error_msg); + if (oat_dex_file == nullptr) { + *error_msg = StringPrintf("Failed finding oat dex file for %s %s", + oat_file->GetLocation().c_str(), + dex_file_location.c_str()); + return false; + } + std::string inner_error_msg; + std::unique_ptr<const DexFile> dex_file = oat_dex_file->OpenDexFile(&inner_error_msg); if (dex_file == nullptr) { - LOG(FATAL) << "Failed to open dex file " << dex_file_location - << " from within oat file " << oat_file->GetLocation() - << " error '" << error_msg << "'"; - UNREACHABLE(); + *error_msg = StringPrintf("Failed to open dex file %s from within oat file %s error '%s'", + dex_file_location.c_str(), + oat_file->GetLocation().c_str(), + inner_error_msg.c_str()); + return false; } if (kSanityCheckObjects) { @@ -920,13 +939,22 @@ void ClassLinker::InitFromImage() { space); } - CHECK_EQ(dex_file->GetLocationChecksum(), oat_dex_file->GetDexFileLocationChecksum()); + if (dex_file->GetLocationChecksum() != oat_dex_file->GetDexFileLocationChecksum()) { + *error_msg = StringPrintf("Checksums do not match for %s: %x vs %x", + dex_file_location.c_str(), + dex_file->GetLocationChecksum(), + oat_dex_file->GetDexFileLocationChecksum()); + return false; + } AppendToBootClassPath(*dex_file.get(), dex_cache); opened_dex_files_.push_back(std::move(dex_file)); } - CHECK(ValidPointerSize(image_pointer_size_)) << image_pointer_size_; + if (!ValidPointerSize(image_pointer_size_)) { + *error_msg = StringPrintf("Invalid image pointer size: %zu", image_pointer_size_); + return false; + } // Set classes on AbstractMethod early so that IsMethod tests can be performed during the live // bitmap walk. @@ -934,7 +962,12 @@ void ClassLinker::InitFromImage() { // Only the Aot compiler supports having an image with a different pointer size than the // runtime. This happens on the host for compile 32 bit tests since we use a 64 bit libart // compiler. We may also use 32 bit dex2oat on a system with 64 bit apps. - CHECK_EQ(image_pointer_size_, sizeof(void*)); + if (image_pointer_size_ != sizeof(void*)) { + *error_msg = StringPrintf("Runtime must use current image pointer size: %zu vs %zu", + image_pointer_size_ , + sizeof(void*)); + return false; + } } if (kSanityCheckObjects) { @@ -987,6 +1020,8 @@ void ClassLinker::InitFromImage() { FinishInit(self); VLOG(startup) << "ClassLinker::InitFromImage exiting"; + + return true; } bool ClassLinker::ClassInClassTable(mirror::Class* klass) { diff --git a/runtime/class_linker.h b/runtime/class_linker.h index a72b58602f..5ba9652c94 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -115,12 +115,15 @@ class ClassLinker { ~ClassLinker(); // Initialize class linker by bootstraping from dex files. - void InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> boot_class_path) + bool InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> boot_class_path, + std::string* error_msg) SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!dex_lock_); // Initialize class linker from one or more images. - void InitFromImage() SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!dex_lock_); + bool InitFromImage(std::string* error_msg) + SHARED_REQUIRES(Locks::mutator_lock_) + REQUIRES(!dex_lock_); // Finds a class by its descriptor, loading it if necessary. // If class_loader is null, searches boot_class_path_. diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 92a56a9b6e..db30a90345 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -1041,8 +1041,13 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) class_linker_ = new ClassLinker(intern_table_); if (GetHeap()->HasImageSpace()) { ATRACE_BEGIN("InitFromImage"); - class_linker_->InitFromImage(); + std::string error_msg; + bool result = class_linker_->InitFromImage(&error_msg); ATRACE_END(); + if (!result) { + LOG(ERROR) << "Could not initialize from image: " << error_msg; + return false; + } if (kIsDebugBuild) { GetHeap()->GetBootImageSpace()->VerifyImageAllocations(); } @@ -1074,7 +1079,11 @@ bool Runtime::Init(const RuntimeOptions& raw_options, bool ignore_unrecognized) runtime_options.GetOrDefault(Opt::Image), &boot_class_path); instruction_set_ = runtime_options.GetOrDefault(Opt::ImageInstructionSet); - class_linker_->InitWithoutImage(std::move(boot_class_path)); + std::string error_msg; + if (!class_linker_->InitWithoutImage(std::move(boot_class_path), &error_msg)) { + LOG(ERROR) << "Could not initialize without image: " << error_msg; + return false; + } // TODO: Should we move the following to InitWithoutImage? SetInstructionSet(instruction_set_); |