diff options
author | 2021-03-19 14:48:40 +0000 | |
---|---|---|
committer | 2021-03-22 14:03:36 +0000 | |
commit | 5b0b2e1b5d60514b829f99aed5712dcae3647115 (patch) | |
tree | 45b58e4e97de2112fd0903a7de0d6a5a86ff3ba6 | |
parent | f0407cf39600b2e87ee6c18f066df2987bd4ba29 (diff) |
Explictly pass VerifierDeps when asking for class verification.
This will simplify creating and populating VerifierDeps at runtime,
which is needed for doing and saving background verifcation of secondary
dex files.
Test: test.py
Bug: 158463186
Change-Id: Ic17913ebd173700e866ba9309bf6ae131fcbc423
-rw-r--r-- | dex2oat/driver/compiler_driver.cc | 11 | ||||
-rw-r--r-- | dex2oat/verifier_deps_test.cc | 20 | ||||
-rw-r--r-- | openjdkjvmti/ti_redefine.cc | 1 | ||||
-rw-r--r-- | runtime/aot_class_linker.cc | 12 | ||||
-rw-r--r-- | runtime/aot_class_linker.h | 1 | ||||
-rw-r--r-- | runtime/class_linker.cc | 20 | ||||
-rw-r--r-- | runtime/class_linker.h | 7 | ||||
-rw-r--r-- | runtime/jit/jit.cc | 3 | ||||
-rw-r--r-- | runtime/oat_file_manager.cc | 2 | ||||
-rw-r--r-- | runtime/transaction_test.cc | 8 | ||||
-rw-r--r-- | runtime/verifier/class_verifier.cc | 9 | ||||
-rw-r--r-- | runtime/verifier/class_verifier.h | 6 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 14 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 17 | ||||
-rw-r--r-- | runtime/verifier/method_verifier_test.cc | 10 | ||||
-rw-r--r-- | runtime/verifier/reg_type-inl.h | 14 | ||||
-rw-r--r-- | runtime/verifier/reg_type.cc | 6 | ||||
-rw-r--r-- | runtime/verifier/verifier_deps.cc | 43 | ||||
-rw-r--r-- | runtime/verifier/verifier_deps.h | 9 | ||||
-rw-r--r-- | tools/art_verifier/art_verifier.cc | 1 |
20 files changed, 145 insertions, 69 deletions
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc index 9d14608170..c94c57f865 100644 --- a/dex2oat/driver/compiler_driver.cc +++ b/dex2oat/driver/compiler_driver.cc @@ -1899,6 +1899,7 @@ class VerifyClassVisitor : public CompilationVisitor { std::string error_msg; failure_kind = verifier::ClassVerifier::VerifyClass(soa.Self(), + soa.Self()->GetVerifierDeps(), &dex_file, dex_cache, class_loader, @@ -1938,7 +1939,10 @@ class VerifyClassVisitor : public CompilationVisitor { return; // Do not update state. } else if (!SkipClass(jclass_loader, dex_file, klass.Get())) { CHECK(klass->IsResolved()) << klass->PrettyClass(); - failure_kind = class_linker->VerifyClass(soa.Self(), klass, log_level_); + failure_kind = class_linker->VerifyClass(soa.Self(), + soa.Self()->GetVerifierDeps(), + klass, + log_level_); if (klass->IsErroneous()) { // ClassLinker::VerifyClass throws, which isn't useful in the compiler. @@ -1994,7 +1998,10 @@ class VerifyClassVisitor : public CompilationVisitor { // Make the skip a soft failure, essentially being considered as verify at runtime. failure_kind = verifier::FailureKind::kSoftFailure; } - verifier::VerifierDeps::MaybeRecordVerificationStatus(dex_file, class_def, failure_kind); + verifier::VerifierDeps::MaybeRecordVerificationStatus(soa.Self()->GetVerifierDeps(), + dex_file, + class_def, + failure_kind); soa.Self()->AssertNoPendingException(); } diff --git a/dex2oat/verifier_deps_test.cc b/dex2oat/verifier_deps_test.cc index f37248ddf6..e833180eb9 100644 --- a/dex2oat/verifier_deps_test.cc +++ b/dex2oat/verifier_deps_test.cc @@ -163,9 +163,9 @@ class VerifierDepsTest : public CommonCompilerDriverTest { method.GetInvokeType(class_def->access_flags_)); CHECK(resolved_method != nullptr); if (method_name == resolved_method->GetName()) { - soa.Self()->SetVerifierDeps(callbacks_->GetVerifierDeps()); std::unique_ptr<MethodVerifier> verifier( MethodVerifier::CreateVerifier(soa.Self(), + callbacks_->GetVerifierDeps(), primary_dex_file_, dex_cache_handle, class_loader_handle, @@ -547,25 +547,23 @@ TEST_F(VerifierDepsTest, UnverifiedOrder) { ASSERT_GT(dex_files.size(), 0u); const DexFile* dex_file = dex_files[0]; VerifierDeps deps1(dex_files); - Thread* const self = Thread::Current(); - ASSERT_TRUE(self->GetVerifierDeps() == nullptr); - self->SetVerifierDeps(&deps1); - deps1.MaybeRecordVerificationStatus(*dex_file, + deps1.MaybeRecordVerificationStatus(&deps1, + *dex_file, dex_file->GetClassDef(0u), verifier::FailureKind::kHardFailure); - deps1.MaybeRecordVerificationStatus(*dex_file, + deps1.MaybeRecordVerificationStatus(&deps1, + *dex_file, dex_file->GetClassDef(1u), verifier::FailureKind::kHardFailure); VerifierDeps deps2(dex_files); - self->SetVerifierDeps(nullptr); - self->SetVerifierDeps(&deps2); - deps2.MaybeRecordVerificationStatus(*dex_file, + deps2.MaybeRecordVerificationStatus(&deps2, + *dex_file, dex_file->GetClassDef(1u), verifier::FailureKind::kHardFailure); - deps2.MaybeRecordVerificationStatus(*dex_file, + deps2.MaybeRecordVerificationStatus(&deps2, + *dex_file, dex_file->GetClassDef(0u), verifier::FailureKind::kHardFailure); - self->SetVerifierDeps(nullptr); std::vector<uint8_t> buffer1; deps1.Encode(dex_files, &buffer1); std::vector<uint8_t> buffer2; diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index 487d9dae4d..b2b839b069 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -1613,6 +1613,7 @@ bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& // TODO Make verification log level lower art::verifier::FailureKind failure = art::verifier::ClassVerifier::VerifyClass(driver_->self_, + /*verifier_deps=*/nullptr, dex_file_.get(), hs.NewHandle(iter.GetNewDexCache()), hs.NewHandle(GetClassLoader()), diff --git a/runtime/aot_class_linker.cc b/runtime/aot_class_linker.cc index 505946646d..5d8b61df7c 100644 --- a/runtime/aot_class_linker.cc +++ b/runtime/aot_class_linker.cc @@ -103,10 +103,12 @@ bool AotClassLinker::InitializeClass(Thread* self, return success; } -verifier::FailureKind AotClassLinker::PerformClassVerification(Thread* self, - Handle<mirror::Class> klass, - verifier::HardFailLogMode log_level, - std::string* error_msg) { +verifier::FailureKind AotClassLinker::PerformClassVerification( + Thread* self, + verifier::VerifierDeps* verifier_deps, + Handle<mirror::Class> klass, + verifier::HardFailLogMode log_level, + std::string* error_msg) { Runtime* const runtime = Runtime::Current(); CompilerCallbacks* callbacks = runtime->GetCompilerCallbacks(); ClassStatus old_status = callbacks->GetPreviousClassState( @@ -125,7 +127,7 @@ verifier::FailureKind AotClassLinker::PerformClassVerification(Thread* self, return verifier::FailureKind::kSoftFailure; } // Do the actual work. - return ClassLinker::PerformClassVerification(self, klass, log_level, error_msg); + return ClassLinker::PerformClassVerification(self, verifier_deps, klass, log_level, error_msg); } bool AotClassLinker::CanReferenceInBootImageExtension(ObjPtr<mirror::Class> klass, gc::Heap* heap) { diff --git a/runtime/aot_class_linker.h b/runtime/aot_class_linker.h index a094e3a174..9be8869faa 100644 --- a/runtime/aot_class_linker.h +++ b/runtime/aot_class_linker.h @@ -52,6 +52,7 @@ static bool CanReferenceInBootImageExtension(ObjPtr<mirror::Class> klass, gc::He // Overridden version of PerformClassVerification allows skipping verification if the class was // previously verified but unloaded. verifier::FailureKind PerformClassVerification(Thread* self, + verifier::VerifierDeps* verifier_deps, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level, std::string* error_msg) diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 11b54809e6..e894037ae3 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -4464,6 +4464,7 @@ void ClassLinker::LookupClasses(const char* descriptor, } bool ClassLinker::AttemptSupertypeVerification(Thread* self, + verifier::VerifierDeps* verifier_deps, Handle<mirror::Class> klass, Handle<mirror::Class> supertype) { DCHECK(self != nullptr); @@ -4471,7 +4472,7 @@ bool ClassLinker::AttemptSupertypeVerification(Thread* self, DCHECK(supertype != nullptr); if (!supertype->IsVerified() && !supertype->IsErroneous()) { - VerifyClass(self, supertype); + VerifyClass(self, verifier_deps, supertype); } if (supertype->IsVerified() @@ -4508,8 +4509,10 @@ bool ClassLinker::AttemptSupertypeVerification(Thread* self, return false; } -verifier::FailureKind ClassLinker::VerifyClass( - Thread* self, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level) { +verifier::FailureKind ClassLinker::VerifyClass(Thread* self, + verifier::VerifierDeps* verifier_deps, + Handle<mirror::Class> klass, + verifier::HardFailLogMode log_level) { { // TODO: assert that the monitor on the Class is held ObjectLock<mirror::Class> lock(self, klass); @@ -4577,7 +4580,8 @@ verifier::FailureKind ClassLinker::VerifyClass( StackHandleScope<2> hs(self); MutableHandle<mirror::Class> supertype(hs.NewHandle(klass->GetSuperClass())); // If we have a superclass and we get a hard verification failure we can return immediately. - if (supertype != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) { + if (supertype != nullptr && + !AttemptSupertypeVerification(self, verifier_deps, klass, supertype)) { CHECK(self->IsExceptionPending()) << "Verification error should be pending."; return verifier::FailureKind::kHardFailure; } @@ -4603,7 +4607,7 @@ verifier::FailureKind ClassLinker::VerifyClass( // We only care if we have default interfaces and can skip if we are already verified... if (LIKELY(!iface->HasDefaultMethods() || iface->IsVerified())) { continue; - } else if (UNLIKELY(!AttemptSupertypeVerification(self, klass, iface))) { + } else if (UNLIKELY(!AttemptSupertypeVerification(self, verifier_deps, klass, iface))) { // We had a hard failure while verifying this interface. Just return immediately. CHECK(self->IsExceptionPending()) << "Verification error should be pending."; return verifier::FailureKind::kHardFailure; @@ -4643,7 +4647,7 @@ verifier::FailureKind ClassLinker::VerifyClass( std::string error_msg; verifier::FailureKind verifier_failure = verifier::FailureKind::kNoFailure; if (!preverified) { - verifier_failure = PerformClassVerification(self, klass, log_level, &error_msg); + verifier_failure = PerformClassVerification(self, verifier_deps, klass, log_level, &error_msg); } // Verification is done, grab the lock again. @@ -4728,11 +4732,13 @@ verifier::FailureKind ClassLinker::VerifyClass( } verifier::FailureKind ClassLinker::PerformClassVerification(Thread* self, + verifier::VerifierDeps* verifier_deps, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level, std::string* error_msg) { Runtime* const runtime = Runtime::Current(); return verifier::ClassVerifier::VerifyClass(self, + verifier_deps, klass.Get(), runtime->GetCompilerCallbacks(), runtime->IsAotCompiler(), @@ -5233,7 +5239,7 @@ bool ClassLinker::InitializeClass(Thread* self, << klass->PrettyClass() << ": state=" << klass->GetStatus(); if (!klass->IsVerified()) { - VerifyClass(self, klass); + VerifyClass(self, /*verifier_deps= */ nullptr, klass); if (!klass->IsVerified()) { // We failed to verify, expect either the klass to be erroneous or verification failed at // compile time. diff --git a/runtime/class_linker.h b/runtime/class_linker.h index 95dc6cfaff..d6e34ffed1 100644 --- a/runtime/class_linker.h +++ b/runtime/class_linker.h @@ -98,6 +98,10 @@ using MethodDexCachePair = NativeDexCachePair<ArtMethod>; using MethodDexCacheType = std::atomic<MethodDexCachePair>; } // namespace mirror +namespace verifier { +class VerifierDeps; +} + class ClassVisitor { public: virtual ~ClassVisitor() {} @@ -553,6 +557,7 @@ class ClassLinker { verifier::FailureKind VerifyClass( Thread* self, + verifier::VerifierDeps* verifier_deps, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone) REQUIRES_SHARED(Locks::mutator_lock_) @@ -851,6 +856,7 @@ class ClassLinker { REQUIRES(!Locks::dex_lock_); virtual verifier::FailureKind PerformClassVerification(Thread* self, + verifier::VerifierDeps* verifier_deps, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level, std::string* error_msg) @@ -882,6 +888,7 @@ class ClassLinker { // appropriate exceptions if verification failed hard. Returns true for successful verification or // soft-failures. bool AttemptSupertypeVerification(Thread* self, + verifier::VerifierDeps* verifier_deps, Handle<mirror::Class> klass, Handle<mirror::Class> supertype) REQUIRES(!Locks::dex_lock_) diff --git a/runtime/jit/jit.cc b/runtime/jit/jit.cc index d7583b1608..0af9aa3ec9 100644 --- a/runtime/jit/jit.cc +++ b/runtime/jit/jit.cc @@ -909,7 +909,8 @@ class ZygoteVerificationTask final : public Task { continue; } ++number_of_classes; - if (linker->VerifyClass(self, klass) == verifier::FailureKind::kHardFailure) { + if (linker->VerifyClass(self, /* verifier_deps= */ nullptr, klass) == + verifier::FailureKind::kHardFailure) { DCHECK(self->IsExceptionPending()); LOG(FATAL) << "Methods in the boot classpath failed to verify: " << self->GetException()->Dump(); diff --git a/runtime/oat_file_manager.cc b/runtime/oat_file_manager.cc index 8a0f550ca2..25a24134ba 100644 --- a/runtime/oat_file_manager.cc +++ b/runtime/oat_file_manager.cc @@ -735,7 +735,7 @@ class BackgroundVerificationTask final : public Task { } CHECK(h_class->IsResolved()) << h_class->PrettyDescriptor(); - class_linker->VerifyClass(self, h_class); + class_linker->VerifyClass(self, &verifier_deps, h_class); if (h_class->IsErroneous()) { // ClassLinker::VerifyClass throws, which isn't useful here. CHECK(soa.Self()->IsExceptionPending()); diff --git a/runtime/transaction_test.cc b/runtime/transaction_test.cc index 2964427322..91eafabf77 100644 --- a/runtime/transaction_test.cc +++ b/runtime/transaction_test.cc @@ -63,13 +63,13 @@ class TransactionTest : public CommonRuntimeTest { h_klass.Assign(class_linker_->FindClass(soa.Self(), "LTransaction$AbortHelperClass;", class_loader)); ASSERT_TRUE(h_klass != nullptr); - class_linker_->VerifyClass(soa.Self(), h_klass); + class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass); ASSERT_TRUE(h_klass->IsVerified()); // Load and verify tested class. h_klass.Assign(class_linker_->FindClass(soa.Self(), tested_class_signature, class_loader)); ASSERT_TRUE(h_klass != nullptr); - class_linker_->VerifyClass(soa.Self(), h_klass); + class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass); ASSERT_TRUE(h_klass->IsVerified()); ClassStatus old_status = h_klass->GetStatus(); @@ -543,7 +543,7 @@ TEST_F(TransactionTest, EmptyClass) { hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$EmptyStatic;", class_loader))); ASSERT_TRUE(h_klass != nullptr); - class_linker_->VerifyClass(soa.Self(), h_klass); + class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass); ASSERT_TRUE(h_klass->IsVerified()); EnterTransactionMode(); @@ -566,7 +566,7 @@ TEST_F(TransactionTest, StaticFieldClass) { hs.NewHandle(class_linker_->FindClass(soa.Self(), "LTransaction$StaticFieldClass;", class_loader))); ASSERT_TRUE(h_klass != nullptr); - class_linker_->VerifyClass(soa.Self(), h_klass); + class_linker_->VerifyClass(soa.Self(), /* verifier_deps= */ nullptr, h_klass); ASSERT_TRUE(h_klass->IsVerified()); EnterTransactionMode(); diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc index 5b6a07d778..7559f98884 100644 --- a/runtime/verifier/class_verifier.cc +++ b/runtime/verifier/class_verifier.cc @@ -113,6 +113,7 @@ FailureKind ClassVerifier::ReverifyClass(Thread* self, }; DelayedVerifyCallback dvc; FailureKind res = CommonVerifyClass(self, + /*verifier_deps=*/nullptr, h_klass.Get(), /*callbacks=*/nullptr, &dvc, @@ -128,6 +129,7 @@ FailureKind ClassVerifier::ReverifyClass(Thread* self, } FailureKind ClassVerifier::VerifyClass(Thread* self, + VerifierDeps* verifier_deps, ObjPtr<mirror::Class> klass, CompilerCallbacks* callbacks, bool allow_soft_failures, @@ -139,6 +141,7 @@ FailureKind ClassVerifier::VerifyClass(Thread* self, } StandardVerifyCallback svc; return CommonVerifyClass(self, + verifier_deps, klass, callbacks, &svc, @@ -149,6 +152,7 @@ FailureKind ClassVerifier::VerifyClass(Thread* self, } FailureKind ClassVerifier::CommonVerifyClass(Thread* self, + VerifierDeps* verifier_deps, ObjPtr<mirror::Class> klass, CompilerCallbacks* callbacks, VerifierCallback* verifier_callback, @@ -184,6 +188,7 @@ FailureKind ClassVerifier::CommonVerifyClass(Thread* self, Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache())); Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader())); return VerifyClass(self, + verifier_deps, &dex_file, dex_cache, class_loader, @@ -198,6 +203,7 @@ FailureKind ClassVerifier::CommonVerifyClass(Thread* self, FailureKind ClassVerifier::VerifyClass(Thread* self, + VerifierDeps* verifier_deps, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, @@ -209,6 +215,7 @@ FailureKind ClassVerifier::VerifyClass(Thread* self, std::string* error) { StandardVerifyCallback svc; return VerifyClass(self, + verifier_deps, dex_file, dex_cache, class_loader, @@ -222,6 +229,7 @@ FailureKind ClassVerifier::VerifyClass(Thread* self, } FailureKind ClassVerifier::VerifyClass(Thread* self, + VerifierDeps* verifier_deps, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, @@ -273,6 +281,7 @@ FailureKind ClassVerifier::VerifyClass(Thread* self, MethodVerifier::VerifyMethod(self, linker, Runtime::Current()->GetArenaPool(), + verifier_deps, method_idx, dex_file, dex_cache, diff --git a/runtime/verifier/class_verifier.h b/runtime/verifier/class_verifier.h index 0b229662e8..fa9dd97e3c 100644 --- a/runtime/verifier/class_verifier.h +++ b/runtime/verifier/class_verifier.h @@ -49,6 +49,8 @@ class ClassLoader; namespace verifier { +class VerifierDeps; + // Verifier that ensures the complete class is OK. class ClassVerifier { public: @@ -64,6 +66,7 @@ class ClassVerifier { REQUIRES_SHARED(Locks::mutator_lock_); // Verify a class. Returns "kNoFailure" on success. static FailureKind VerifyClass(Thread* self, + VerifierDeps* verifier_deps, ObjPtr<mirror::Class> klass, CompilerCallbacks* callbacks, bool allow_soft_failures, @@ -72,6 +75,7 @@ class ClassVerifier { std::string* error) REQUIRES_SHARED(Locks::mutator_lock_); static FailureKind VerifyClass(Thread* self, + VerifierDeps* verifier_deps, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, @@ -91,6 +95,7 @@ class ClassVerifier { private: static FailureKind CommonVerifyClass(Thread* self, + VerifierDeps* verifier_deps, ObjPtr<mirror::Class> klass, CompilerCallbacks* callbacks, VerifierCallback* verifier_callback, @@ -101,6 +106,7 @@ class ClassVerifier { REQUIRES_SHARED(Locks::mutator_lock_); static FailureKind VerifyClass(Thread* self, + VerifierDeps* verifier_deps, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 57614299e0..59e9fbafe3 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -153,6 +153,7 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { MethodVerifier(Thread* self, ClassLinker* class_linker, ArenaPool* arena_pool, + VerifierDeps* verifier_deps, const DexFile* dex_file, const dex::CodeItem* code_item, uint32_t method_idx, @@ -172,6 +173,7 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { : art::verifier::MethodVerifier(self, class_linker, arena_pool, + verifier_deps, dex_file, class_def, code_item, @@ -5075,6 +5077,7 @@ const RegType& MethodVerifier<kVerifierDebug>::DetermineCat1Constant(int32_t val MethodVerifier::MethodVerifier(Thread* self, ClassLinker* class_linker, ArenaPool* arena_pool, + VerifierDeps* verifier_deps, const DexFile* dex_file, const dex::ClassDef& class_def, const dex::CodeItem* code_item, @@ -5099,6 +5102,7 @@ MethodVerifier::MethodVerifier(Thread* self, can_load_classes_(can_load_classes), allow_soft_failures_(allow_soft_failures), class_linker_(class_linker), + verifier_deps_(verifier_deps), link_(nullptr) { self->PushVerifier(this); } @@ -5111,6 +5115,7 @@ MethodVerifier::~MethodVerifier() { MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, ClassLinker* class_linker, ArenaPool* arena_pool, + VerifierDeps* verifier_deps, uint32_t method_idx, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, @@ -5131,6 +5136,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, return VerifyMethod<true>(self, class_linker, arena_pool, + verifier_deps, method_idx, dex_file, dex_cache, @@ -5151,6 +5157,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, return VerifyMethod<false>(self, class_linker, arena_pool, + verifier_deps, method_idx, dex_file, dex_cache, @@ -5190,6 +5197,7 @@ template <bool kVerifierDebug> MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, ClassLinker* class_linker, ArenaPool* arena_pool, + VerifierDeps* verifier_deps, uint32_t method_idx, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, @@ -5212,6 +5220,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, impl::MethodVerifier<kVerifierDebug> verifier(self, class_linker, arena_pool, + verifier_deps, dex_file, code_item, method_idx, @@ -5367,6 +5376,7 @@ MethodVerifier* MethodVerifier::CalculateVerificationInfo( new impl::MethodVerifier<false>(self, Runtime::Current()->GetClassLinker(), Runtime::Current()->GetArenaPool(), + /* verifier_deps= */ nullptr, method->GetDexFile(), method->GetCodeItem(), method->GetDexMethodIndex(), @@ -5414,6 +5424,7 @@ MethodVerifier* MethodVerifier::VerifyMethodAndDump(Thread* self, self, Runtime::Current()->GetClassLinker(), Runtime::Current()->GetArenaPool(), + /* verifier_deps= */ nullptr, dex_file, code_item, dex_method_idx, @@ -5455,6 +5466,7 @@ void MethodVerifier::FindLocksAtDexPc( impl::MethodVerifier<false> verifier(hs.Self(), Runtime::Current()->GetClassLinker(), Runtime::Current()->GetArenaPool(), + /* verifier_deps= */ nullptr, m->GetDexFile(), m->GetCodeItem(), m->GetDexMethodIndex(), @@ -5477,6 +5489,7 @@ void MethodVerifier::FindLocksAtDexPc( } MethodVerifier* MethodVerifier::CreateVerifier(Thread* self, + VerifierDeps* verifier_deps, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, @@ -5494,6 +5507,7 @@ MethodVerifier* MethodVerifier::CreateVerifier(Thread* self, return new impl::MethodVerifier<false>(self, Runtime::Current()->GetClassLinker(), Runtime::Current()->GetArenaPool(), + verifier_deps, dex_file, code_item, method_idx, diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 4d4dd5b31b..1dfcaabb23 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -62,6 +62,7 @@ class RegisterLine; using RegisterLineArenaUniquePtr = std::unique_ptr<RegisterLine, RegisterLineArenaDelete>; class RegType; struct ScopedNewLine; +class VerifierDeps; // We don't need to store the register data for many instructions, because we either only need // it at branch points (for verification) or GC points and branches (for verification + @@ -203,11 +204,11 @@ class MethodVerifier { virtual const RegType& ResolveCheckedClass(dex::TypeIndex class_idx) REQUIRES_SHARED(Locks::mutator_lock_) = 0; - uint32_t GetEncounteredFailureTypes() { + uint32_t GetEncounteredFailureTypes() const { return encountered_failure_types_; } - ClassLinker* GetClassLinker() { + ClassLinker* GetClassLinker() const { return class_linker_; } @@ -215,10 +216,15 @@ class MethodVerifier { return flags_.aot_mode_; } + VerifierDeps* GetVerifierDeps() const { + return verifier_deps_; + } + protected: MethodVerifier(Thread* self, ClassLinker* class_linker, ArenaPool* arena_pool, + VerifierDeps* verifier_deps, const DexFile* dex_file, const dex::ClassDef& class_def, const dex::CodeItem* code_item, @@ -253,6 +259,7 @@ class MethodVerifier { static FailureData VerifyMethod(Thread* self, ClassLinker* class_linker, ArenaPool* arena_pool, + VerifierDeps* verifier_deps, uint32_t method_idx, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, @@ -275,6 +282,7 @@ class MethodVerifier { static FailureData VerifyMethod(Thread* self, ClassLinker* class_linker, ArenaPool* arena_pool, + VerifierDeps* verifier_deps, uint32_t method_idx, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, @@ -299,6 +307,7 @@ class MethodVerifier { // has an irrecoverable corruption. virtual bool Verify() REQUIRES_SHARED(Locks::mutator_lock_) = 0; static MethodVerifier* CreateVerifier(Thread* self, + VerifierDeps* verifier_deps, const DexFile* dex_file, Handle<mirror::DexCache> dex_cache, Handle<mirror::ClassLoader> class_loader, @@ -386,6 +395,10 @@ class MethodVerifier { // Classlinker to use when resolving. ClassLinker* class_linker_; + // The verifier deps object we are going to report type assigability + // constraints to. Can be null for runtime verification. + VerifierDeps* verifier_deps_; + // Link, for the method verifier root linked list. MethodVerifier* link_; diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc index 800e8a1d16..976198240b 100644 --- a/runtime/verifier/method_verifier_test.cc +++ b/runtime/verifier/method_verifier_test.cc @@ -45,8 +45,14 @@ class MethodVerifierTest : public CommonRuntimeTest { // Verify the class std::string error_msg; - FailureKind failure = ClassVerifier::VerifyClass( - self, klass, nullptr, true, HardFailLogMode::kLogWarning, /* api_level= */ 0u, &error_msg); + FailureKind failure = ClassVerifier::VerifyClass(self, + /* verifier_deps= */ nullptr, + klass, + nullptr, + true, + HardFailLogMode::kLogWarning, + /* api_level= */ 0u, + &error_msg); if (android::base::StartsWith(descriptor, "Ljava/lang/invoke")) { ASSERT_TRUE(failure == FailureKind::kSoftFailure || diff --git a/runtime/verifier/reg_type-inl.h b/runtime/verifier/reg_type-inl.h index b6af1d3006..efe03a8d0c 100644 --- a/runtime/verifier/reg_type-inl.h +++ b/runtime/verifier/reg_type-inl.h @@ -116,16 +116,22 @@ inline bool RegType::AssignableFrom(const RegType& lhs, // Record assignability dependency. The `verifier` is null during unit tests and // VerifiedMethod::GenerateSafeCastSet. if (verifier != nullptr && result) { - VerifierDeps::MaybeRecordAssignability( - verifier->GetDexFile(), verifier->GetClassDef(), lhs.GetClass(), rhs.GetClass()); + VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(), + verifier->GetDexFile(), + verifier->GetClassDef(), + lhs.GetClass(), + rhs.GetClass()); } return result; } else { // For unresolved types, we don't know if they are assignable, and the // verifier will continue assuming they are. We need to record that. if (verifier != nullptr) { - VerifierDeps::MaybeRecordAssignability( - verifier->GetDexFile(), verifier->GetClassDef(), lhs, rhs); + VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(), + verifier->GetDexFile(), + verifier->GetClassDef(), + lhs, + rhs); } // Unresolved types are only assignable for null and equality. // Null cannot be the left-hand side. diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index 351aa55214..5af2d4b74f 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -901,11 +901,13 @@ const RegType& RegType::Merge(const RegType& incoming_type, // Record the dependency that both `GetClass()` and `incoming_type.GetClass()` // are assignable to `join_class`. The `verifier` is null during unit tests. if (verifier != nullptr) { - VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(), + VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(), + verifier->GetDexFile(), verifier->GetClassDef(), join_class, GetClass()); - VerifierDeps::MaybeRecordAssignability(verifier->GetDexFile(), + VerifierDeps::MaybeRecordAssignability(verifier->GetVerifierDeps(), + verifier->GetDexFile(), verifier->GetClassDef(), join_class, incoming_type.GetClass()); diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc index 7a27a0152a..c9128f831a 100644 --- a/runtime/verifier/verifier_deps.cc +++ b/runtime/verifier/verifier_deps.cc @@ -112,25 +112,18 @@ dex::StringIndex VerifierDeps::GetClassDescriptorStringId(const DexFile& dex_fil return GetIdFromString(dex_file, klass->GetDescriptor(&temp)); } -static inline VerifierDeps* GetMainVerifierDeps() { +static inline VerifierDeps* GetMainVerifierDeps(VerifierDeps* local_deps) { // The main VerifierDeps is the one set in the compiler callbacks, which at the // end of verification will have all the per-thread VerifierDeps merged into it. CompilerCallbacks* callbacks = Runtime::Current()->GetCompilerCallbacks(); if (callbacks == nullptr) { - return nullptr; + DCHECK(!Runtime::Current()->IsAotCompiler()); + return local_deps; } + DCHECK(Runtime::Current()->IsAotCompiler()); return callbacks->GetVerifierDeps(); } -static inline VerifierDeps* GetThreadLocalVerifierDeps() { - // During AOT, each thread has its own VerifierDeps, to avoid lock contention. At the end - // of full verification, these VerifierDeps will be merged into the main one. - if (!Runtime::Current()->IsAotCompiler()) { - return nullptr; - } - return Thread::Current()->GetVerifierDeps(); -} - static bool FindExistingStringId(const std::vector<std::string>& strings, const std::string& str, uint32_t* found_id) { @@ -156,7 +149,7 @@ dex::StringIndex VerifierDeps::GetIdFromString(const DexFile& dex_file, const st // We use the main `VerifierDeps` for adding new strings to simplify // synchronization/merging of these entries between threads. - VerifierDeps* singleton = GetMainVerifierDeps(); + VerifierDeps* singleton = GetMainVerifierDeps(this); DexFileDeps* deps = singleton->GetDexFileDeps(dex_file); DCHECK(deps != nullptr); @@ -285,16 +278,16 @@ void VerifierDeps::AddAssignability(const DexFile& dex_file, } } -void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file, +void VerifierDeps::MaybeRecordVerificationStatus(VerifierDeps* verifier_deps, + const DexFile& dex_file, const dex::ClassDef& class_def, FailureKind failure_kind) { - VerifierDeps* thread_deps = GetThreadLocalVerifierDeps(); - if (thread_deps != nullptr) { + if (verifier_deps != nullptr) { switch (failure_kind) { case verifier::FailureKind::kHardFailure: case verifier::FailureKind::kSoftFailure: { // Class will be verified at runtime. - DexFileDeps* dex_deps = thread_deps->GetDexFileDeps(dex_file); + DexFileDeps* dex_deps = verifier_deps->GetDexFileDeps(dex_file); uint16_t index = dex_file.GetIndexForClassDef(class_def); dex_deps->assignable_types_[index].clear(); break; @@ -302,7 +295,7 @@ void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file, case verifier::FailureKind::kAccessChecksFailure: case verifier::FailureKind::kTypeChecksFailure: case verifier::FailureKind::kNoFailure: { - thread_deps->RecordClassVerified(dex_file, class_def); + verifier_deps->RecordClassVerified(dex_file, class_def); break; } } @@ -315,23 +308,23 @@ void VerifierDeps::RecordClassVerified(const DexFile& dex_file, const dex::Class dex_deps->verified_classes_[dex_file.GetIndexForClassDef(class_def)] = true; } -void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file, +void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps, + const DexFile& dex_file, const dex::ClassDef& class_def, ObjPtr<mirror::Class> destination, ObjPtr<mirror::Class> source) { - VerifierDeps* thread_deps = GetThreadLocalVerifierDeps(); - if (thread_deps != nullptr) { - thread_deps->AddAssignability(dex_file, class_def, destination, source); + if (verifier_deps != nullptr) { + verifier_deps->AddAssignability(dex_file, class_def, destination, source); } } -void VerifierDeps::MaybeRecordAssignability(const DexFile& dex_file, +void VerifierDeps::MaybeRecordAssignability(VerifierDeps* verifier_deps, + const DexFile& dex_file, const dex::ClassDef& class_def, const RegType& destination, const RegType& source) { - VerifierDeps* thread_deps = GetThreadLocalVerifierDeps(); - if (thread_deps != nullptr) { - thread_deps->AddAssignability(dex_file, class_def, destination, source); + if (verifier_deps != nullptr) { + verifier_deps->AddAssignability(dex_file, class_def, destination, source); } } diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h index 40ece5fee4..2e8ef4e27f 100644 --- a/runtime/verifier/verifier_deps.h +++ b/runtime/verifier/verifier_deps.h @@ -80,7 +80,8 @@ class VerifierDeps { REQUIRES(!Locks::verifier_deps_lock_); // Record the verification status of the class defined in `class_def`. - static void MaybeRecordVerificationStatus(const DexFile& dex_file, + static void MaybeRecordVerificationStatus(VerifierDeps* verifier_deps, + const DexFile& dex_file, const dex::ClassDef& class_def, FailureKind failure_kind) REQUIRES(!Locks::verifier_deps_lock_); @@ -88,7 +89,8 @@ class VerifierDeps { // Record the outcome `is_assignable` of type assignability test from `source` // to `destination` as defined by RegType::AssignableFrom. `dex_file` is the // owner of the method for which MethodVerifier performed the assignability test. - static void MaybeRecordAssignability(const DexFile& dex_file, + static void MaybeRecordAssignability(VerifierDeps* verifier_deps, + const DexFile& dex_file, const dex::ClassDef& class_def, ObjPtr<mirror::Class> destination, ObjPtr<mirror::Class> source) @@ -97,7 +99,8 @@ class VerifierDeps { // Record that `source` is assignable to `destination`. `dex_file` is the // owner of the method for which MethodVerifier performed the assignability test. - static void MaybeRecordAssignability(const DexFile& dex_file, + static void MaybeRecordAssignability(VerifierDeps* verifier_deps, + const DexFile& dex_file, const dex::ClassDef& class_def, const RegType& destination, const RegType& source) diff --git a/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc index 6fe27d659d..313c4705d4 100644 --- a/tools/art_verifier/art_verifier.cc +++ b/tools/art_verifier/art_verifier.cc @@ -247,6 +247,7 @@ struct MethodVerifierMain : public CmdlineMain<MethodVerifierArgs> { std::string error_msg; verifier::FailureKind res = verifier::ClassVerifier::VerifyClass(soa.Self(), + /* verifier_deps= */ nullptr, h_klass.Get(), runtime->GetCompilerCallbacks(), true, |