diff options
Diffstat (limited to 'runtime/class_linker.cc')
| -rw-r--r-- | runtime/class_linker.cc | 79 |
1 files changed, 54 insertions, 25 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index d98e0b2c54c..45d1381297e 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -270,9 +270,13 @@ static void WrapExceptionInInitializer(Handle<mirror::Class> klass) // cannot in general be guaranteed, but in all likelihood leads to breakage down the line. if (klass->GetClassLoader() == nullptr && !Runtime::Current()->IsAotCompiler()) { std::string tmp; - LOG(kIsDebugBuild ? FATAL : WARNING) << klass->GetDescriptor(&tmp) - << " failed initialization: " - << self->GetException()->Dump(); + // We want to LOG(FATAL) on debug builds since this really shouldn't be happening but we need to + // make sure to only do it if we don't have AsyncExceptions being thrown around since those + // could have caused the error. + bool known_impossible = kIsDebugBuild && !Runtime::Current()->AreAsyncExceptionsThrown(); + LOG(known_impossible ? FATAL : WARNING) << klass->GetDescriptor(&tmp) + << " failed initialization: " + << self->GetException()->Dump(); } env->ExceptionClear(); @@ -1828,21 +1832,6 @@ bool ClassLinker::AddImageSpace( header.VisitPackedArtMethods(&visitor, space->Begin(), image_pointer_size_); } - if (!app_image) { - // Make the string intern table and class table immutable for boot image. - // PIC app oat files may mmap a read-only copy into their own .bss section, - // so enforce that the data in the boot image tables remains unchanged. - // - // We cannot do that for app image even after the fixup as some interned - // String references may actually end up pointing to moveable Strings. - uint8_t* const_section_begin = space->Begin() + header.GetBootImageConstantTablesOffset(); - CheckedCall(mprotect, - "protect constant tables", - const_section_begin, - header.GetBootImageConstantTablesSize(), - PROT_READ); - } - ClassTable* class_table = nullptr; { WriterMutexLock mu(self, *Locks::classlinker_classes_lock_); @@ -3390,9 +3379,10 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, CHECK_EQ(dex_cache_location, dex_file_suffix); const OatFile* oat_file = (dex_file.GetOatDexFile() != nullptr) ? dex_file.GetOatDexFile()->GetOatFile() : nullptr; - // Clean up pass to remove null dex caches. Also check if we need to initialize OatFile .bss. - // Null dex caches can occur due to class unloading and we are lazily removing null entries. - bool initialize_oat_file_bss = (oat_file != nullptr); + // Clean up pass to remove null dex caches; null dex caches can occur due to class unloading + // and we are lazily removing null entries. Also check if we need to initialize OatFile data + // (.data.bimg.rel.ro and .bss sections) needed for code execution. + bool initialize_oat_file_data = (oat_file != nullptr) && oat_file->IsExecutable(); JavaVMExt* const vm = self->GetJniEnv()->GetVm(); for (auto it = dex_caches_.begin(); it != dex_caches_.end(); ) { DexCacheData data = *it; @@ -3400,15 +3390,36 @@ void ClassLinker::RegisterDexFileLocked(const DexFile& dex_file, vm->DeleteWeakGlobalRef(self, data.weak_root); it = dex_caches_.erase(it); } else { - if (initialize_oat_file_bss && + if (initialize_oat_file_data && it->dex_file->GetOatDexFile() != nullptr && it->dex_file->GetOatDexFile()->GetOatFile() == oat_file) { - initialize_oat_file_bss = false; // Already initialized. + initialize_oat_file_data = false; // Already initialized. } ++it; } } - if (initialize_oat_file_bss) { + if (initialize_oat_file_data) { + // Initialize the .data.bimg.rel.ro section. + if (!oat_file->GetBootImageRelocations().empty()) { + uint8_t* reloc_begin = const_cast<uint8_t*>(oat_file->DataBimgRelRoBegin()); + CheckedCall(mprotect, + "un-protect boot image relocations", + reloc_begin, + oat_file->DataBimgRelRoSize(), + PROT_READ | PROT_WRITE); + uint32_t boot_image_begin = dchecked_integral_cast<uint32_t>(reinterpret_cast<uintptr_t>( + Runtime::Current()->GetHeap()->GetBootImageSpaces().front()->Begin())); + for (const uint32_t& relocation : oat_file->GetBootImageRelocations()) { + const_cast<uint32_t&>(relocation) += boot_image_begin; + } + CheckedCall(mprotect, + "protect boot image relocations", + reloc_begin, + oat_file->DataBimgRelRoSize(), + PROT_READ); + } + + // Initialize the .bss section. // TODO: Pre-initialize from boot/app image? ArtMethod* resolution_method = Runtime::Current()->GetResolutionMethod(); for (ArtMethod*& entry : oat_file->GetBssMethods()) { @@ -6169,7 +6180,7 @@ ArtMethod* ClassLinker::AddMethodToConflictTable(ObjPtr<mirror::Class> klass, // Note that there is a race in the presence of multiple threads and we may leak // memory from the LinearAlloc, but that's a tradeoff compared to using // atomic operations. - QuasiAtomic::ThreadFenceRelease(); + std::atomic_thread_fence(std::memory_order_release); new_conflict_method->SetImtConflictTable(new_table, image_pointer_size_); return new_conflict_method; } @@ -8225,29 +8236,34 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForField( DexFile::MethodHandleType handle_type = static_cast<DexFile::MethodHandleType>(method_handle.method_handle_type_); mirror::MethodHandle::Kind kind; + bool is_put; bool is_static; int32_t num_params; switch (handle_type) { case DexFile::MethodHandleType::kStaticPut: { kind = mirror::MethodHandle::Kind::kStaticPut; + is_put = true; is_static = true; num_params = 1; break; } case DexFile::MethodHandleType::kStaticGet: { kind = mirror::MethodHandle::Kind::kStaticGet; + is_put = false; is_static = true; num_params = 0; break; } case DexFile::MethodHandleType::kInstancePut: { kind = mirror::MethodHandle::Kind::kInstancePut; + is_put = true; is_static = false; num_params = 2; break; } case DexFile::MethodHandleType::kInstanceGet: { kind = mirror::MethodHandle::Kind::kInstanceGet; + is_put = false; is_static = false; num_params = 1; break; @@ -8269,6 +8285,10 @@ mirror::MethodHandle* ClassLinker::ResolveMethodHandleForField( ThrowIllegalAccessErrorField(referring_class, target_field); return nullptr; } + if (UNLIKELY(is_put && target_field->IsFinal())) { + ThrowIllegalAccessErrorField(referring_class, target_field); + return nullptr; + } } else { DCHECK(Thread::Current()->IsExceptionPending()); return nullptr; @@ -8849,6 +8869,15 @@ void ClassLinker::VisitClassLoaders(ClassLoaderVisitor* visitor) const { } } +void ClassLinker::VisitAllocators(AllocatorVisitor* visitor) const { + for (const ClassLoaderData& data : class_loaders_) { + LinearAlloc* alloc = data.allocator; + if (alloc != nullptr && !visitor->Visit(alloc)) { + break; + } + } +} + void ClassLinker::InsertDexFileInToClassLoader(ObjPtr<mirror::Object> dex_file, ObjPtr<mirror::ClassLoader> class_loader) { DCHECK(dex_file != nullptr); |
