diff options
author | 2018-08-24 15:22:43 -0700 | |
---|---|---|
committer | 2018-08-24 15:22:43 -0700 | |
commit | 6cc23acba91d26d7afd6bc681004ac5865a8a163 (patch) | |
tree | d5b6850d7ce511658a33ca417764eac92cafe2d1 | |
parent | e9dce6a280057315a8a58ed46190c9a893c90fba (diff) |
ART: Add API level to verifier
Pass API level to verifier. In preparation for API-level dependent
checks.
Bug: 111969862
Test: m test-art-host
Change-Id: I700ef52e28436a7fda8b9d9ef29841110ed6d3bb
-rw-r--r-- | compiler/driver/compiler_driver.cc | 6 | ||||
-rw-r--r-- | compiler/verifier_deps_test.cc | 3 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 2 | ||||
-rw-r--r-- | openjdkjvmti/ti_redefine.cc | 1 | ||||
-rw-r--r-- | runtime/class_linker.cc | 1 | ||||
-rw-r--r-- | runtime/monitor.cc | 5 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 26 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 19 | ||||
-rw-r--r-- | runtime/verifier/method_verifier_test.cc | 2 | ||||
-rw-r--r-- | tools/art_verifier/art_verifier.cc | 7 |
10 files changed, 56 insertions, 16 deletions
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 6eca304223..3f28aa7c68 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -1886,7 +1886,9 @@ void CompilerDriver::Verify(jobject jclass_loader, class VerifyClassVisitor : public CompilationVisitor { public: VerifyClassVisitor(const ParallelCompilationManager* manager, verifier::HardFailLogMode log_level) - : manager_(manager), log_level_(log_level) {} + : manager_(manager), + log_level_(log_level), + sdk_version_(Runtime::Current()->GetTargetSdkVersion()) {} virtual void Visit(size_t class_def_index) REQUIRES(!Locks::mutator_lock_) OVERRIDE { ScopedTrace trace(__FUNCTION__); @@ -1923,6 +1925,7 @@ class VerifyClassVisitor : public CompilationVisitor { Runtime::Current()->GetCompilerCallbacks(), true /* allow soft failures */, log_level_, + sdk_version_, &error_msg); if (failure_kind == verifier::FailureKind::kHardFailure) { LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor) @@ -1995,6 +1998,7 @@ class VerifyClassVisitor : public CompilationVisitor { private: const ParallelCompilationManager* const manager_; const verifier::HardFailLogMode log_level_; + const uint32_t sdk_version_; }; void CompilerDriver::VerifyDexFile(jobject class_loader, diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc index c223549710..5d76329ee8 100644 --- a/compiler/verifier_deps_test.cc +++ b/compiler/verifier_deps_test.cc @@ -178,7 +178,8 @@ class VerifierDepsTest : public CommonCompilerTest { true /* allow_soft_failures */, true /* need_precise_constants */, false /* verify to dump */, - true /* allow_thread_suspension */); + true /* allow_thread_suspension */, + 0 /* api_level */); verifier.Verify(); soa.Self()->SetVerifierDeps(nullptr); has_failures = verifier.HasFailures(); diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index a5cc38b866..b6bfec6c56 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -1474,7 +1474,7 @@ class OatDumper { } return verifier::MethodVerifier::VerifyMethodAndDump( soa.Self(), vios, dex_method_idx, dex_file, dex_cache, *options_.class_loader_, - class_def, code_item, method, method_access_flags); + class_def, code_item, method, method_access_flags, /* api_level */ 0); } return nullptr; diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc index 8707e272c6..f8c1172073 100644 --- a/openjdkjvmti/ti_redefine.cc +++ b/openjdkjvmti/ti_redefine.cc @@ -1122,6 +1122,7 @@ bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& true, /*allow_soft_failures*/ /*log_level*/ art::verifier::HardFailLogMode::kLogWarning, + art::Runtime::Current()->GetTargetSdkVersion(), &error); switch (failure) { case art::verifier::FailureKind::kNoFailure: diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index f80d34ca2f..bc28a66c87 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -4169,6 +4169,7 @@ verifier::FailureKind ClassLinker::PerformClassVerification(Thread* self, runtime->GetCompilerCallbacks(), runtime->IsAotCompiler(), log_level, + Runtime::Current()->GetTargetSdkVersion(), error_msg); } diff --git a/runtime/monitor.cc b/runtime/monitor.cc index d47bc0d12e..7eabe1d7b2 100644 --- a/runtime/monitor.cc +++ b/runtime/monitor.cc @@ -1401,7 +1401,10 @@ void Monitor::VisitLocks(StackVisitor* stack_visitor, void (*callback)(mirror::O // Ask the verifier for the dex pcs of all the monitor-enter instructions corresponding to // the locks held in this stack frame. std::vector<verifier::MethodVerifier::DexLockInfo> monitor_enter_dex_pcs; - verifier::MethodVerifier::FindLocksAtDexPc(m, dex_pc, &monitor_enter_dex_pcs); + verifier::MethodVerifier::FindLocksAtDexPc(m, + dex_pc, + &monitor_enter_dex_pcs, + Runtime::Current()->GetTargetSdkVersion()); for (verifier::MethodVerifier::DexLockInfo& dex_lock_info : monitor_enter_dex_pcs) { // As a debug check, check that dex PC corresponds to a monitor-enter. if (kIsDebugBuild) { diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index a1b8938eaa..2064fc427e 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -149,6 +149,7 @@ FailureKind MethodVerifier::VerifyClass(Thread* self, CompilerCallbacks* callbacks, bool allow_soft_failures, HardFailLogMode log_level, + uint32_t api_level, std::string* error) { if (klass->IsVerified()) { return FailureKind::kNoFailure; @@ -188,6 +189,7 @@ FailureKind MethodVerifier::VerifyClass(Thread* self, callbacks, allow_soft_failures, log_level, + api_level, error); } @@ -211,6 +213,7 @@ FailureKind MethodVerifier::VerifyClass(Thread* self, CompilerCallbacks* callbacks, bool allow_soft_failures, HardFailLogMode log_level, + uint32_t api_level, std::string* error) { // A class must not be abstract and final. if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) { @@ -261,6 +264,7 @@ FailureKind MethodVerifier::VerifyClass(Thread* self, allow_soft_failures, log_level, /*need_precise_constants*/ false, + api_level, &hard_failure_msg); if (result.kind == FailureKind::kHardFailure) { if (failure_data.kind == FailureKind::kHardFailure) { @@ -322,6 +326,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, bool allow_soft_failures, HardFailLogMode log_level, bool need_precise_constants, + uint32_t api_level, std::string* hard_failure_msg) { MethodVerifier::FailureData result; uint64_t start_ns = kTimeVerifyMethod ? NanoTime() : 0; @@ -339,7 +344,8 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, allow_soft_failures, need_precise_constants, false /* verify to dump */, - true /* allow_thread_suspension */); + true /* allow_thread_suspension */, + api_level); if (verifier.Verify()) { // Verification completed, however failures may be pending that didn't cause the verification // to hard fail. @@ -458,7 +464,8 @@ MethodVerifier* MethodVerifier::VerifyMethodAndDump(Thread* self, const DexFile::ClassDef& class_def, const DexFile::CodeItem* code_item, ArtMethod* method, - uint32_t method_access_flags) { + uint32_t method_access_flags, + uint32_t api_level) { MethodVerifier* verifier = new MethodVerifier(self, dex_file, dex_cache, @@ -472,7 +479,8 @@ MethodVerifier* MethodVerifier::VerifyMethodAndDump(Thread* self, true /* allow_soft_failures */, true /* need_precise_constants */, true /* verify_to_dump */, - true /* allow_thread_suspension */); + true /* allow_thread_suspension */, + api_level); verifier->Verify(); verifier->DumpFailures(vios->Stream()); vios->Stream() << verifier->info_messages_.str(); @@ -500,7 +508,8 @@ MethodVerifier::MethodVerifier(Thread* self, bool allow_soft_failures, bool need_precise_constants, bool verify_to_dump, - bool allow_thread_suspension) + bool allow_thread_suspension, + uint32_t api_level) : self_(self), arena_stack_(Runtime::Current()->GetArenaPool()), allocator_(&arena_stack_), @@ -534,7 +543,8 @@ MethodVerifier::MethodVerifier(Thread* self, verify_to_dump_(verify_to_dump), allow_thread_suspension_(allow_thread_suspension), is_constructor_(false), - link_(nullptr) { + link_(nullptr), + api_level_(api_level == 0 ? std::numeric_limits<uint32_t>::max() : api_level) { self->PushVerifier(this); } @@ -546,7 +556,8 @@ MethodVerifier::~MethodVerifier() { void MethodVerifier::FindLocksAtDexPc( ArtMethod* m, uint32_t dex_pc, - std::vector<MethodVerifier::DexLockInfo>* monitor_enter_dex_pcs) { + std::vector<MethodVerifier::DexLockInfo>* monitor_enter_dex_pcs, + uint32_t api_level) { StackHandleScope<2> hs(Thread::Current()); Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache())); Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader())); @@ -563,7 +574,8 @@ void MethodVerifier::FindLocksAtDexPc( true /* allow_soft_failures */, false /* need_precise_constants */, false /* verify_to_dump */, - false /* allow_thread_suspension */); + false /* allow_thread_suspension */, + api_level); verifier.interesting_dex_pc_ = dex_pc; verifier.monitor_enter_dex_pcs_ = monitor_enter_dex_pcs; verifier.FindLocksAtDexPc(); diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 9890af9d95..eef22807ec 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -100,6 +100,7 @@ class MethodVerifier { CompilerCallbacks* callbacks, bool allow_soft_failures, HardFailLogMode log_level, + uint32_t api_level, std::string* error) REQUIRES_SHARED(Locks::mutator_lock_); static FailureKind VerifyClass(Thread* self, @@ -110,6 +111,7 @@ class MethodVerifier { CompilerCallbacks* callbacks, bool allow_soft_failures, HardFailLogMode log_level, + uint32_t api_level, std::string* error) REQUIRES_SHARED(Locks::mutator_lock_); @@ -121,7 +123,8 @@ class MethodVerifier { Handle<mirror::ClassLoader> class_loader, const DexFile::ClassDef& class_def, const DexFile::CodeItem* code_item, ArtMethod* method, - uint32_t method_access_flags) + uint32_t method_access_flags, + uint32_t api_level) REQUIRES_SHARED(Locks::mutator_lock_); uint8_t EncodePcToReferenceMapData() const; @@ -163,8 +166,10 @@ class MethodVerifier { // Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding // to the locks held at 'dex_pc' in method 'm'. // Note: this is the only situation where the verifier will visit quickened instructions. - static void FindLocksAtDexPc(ArtMethod* m, uint32_t dex_pc, - std::vector<DexLockInfo>* monitor_enter_dex_pcs) + static void FindLocksAtDexPc(ArtMethod* m, + uint32_t dex_pc, + std::vector<DexLockInfo>* monitor_enter_dex_pcs, + uint32_t api_level) REQUIRES_SHARED(Locks::mutator_lock_); static void Init() REQUIRES_SHARED(Locks::mutator_lock_); @@ -242,7 +247,8 @@ class MethodVerifier { bool allow_soft_failures, bool need_precise_constants, bool verify_to_dump, - bool allow_thread_suspension) + bool allow_thread_suspension, + uint32_t api_level) REQUIRES_SHARED(Locks::mutator_lock_); void UninstantiableError(const char* descriptor); @@ -299,6 +305,7 @@ class MethodVerifier { bool allow_soft_failures, HardFailLogMode log_level, bool need_precise_constants, + uint32_t api_level, std::string* hard_failure_msg) REQUIRES_SHARED(Locks::mutator_lock_); @@ -790,6 +797,10 @@ class MethodVerifier { // Link, for the method verifier root linked list. MethodVerifier* link_; + // API level, for dependent checks. Note: we do not use '0' for unset here, to simplify checks. + // Instead, unset level should correspond to max(). + const uint32_t api_level_; + friend class art::Thread; friend class VerifierDepsTest; diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc index d1be9fa6f8..cedc583986 100644 --- a/runtime/verifier/method_verifier_test.cc +++ b/runtime/verifier/method_verifier_test.cc @@ -42,7 +42,7 @@ class MethodVerifierTest : public CommonRuntimeTest { // Verify the class std::string error_msg; FailureKind failure = MethodVerifier::VerifyClass( - self, klass, nullptr, true, HardFailLogMode::kLogWarning, &error_msg); + self, 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/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc index fc62410889..1a76a867f6 100644 --- a/tools/art_verifier/art_verifier.cc +++ b/tools/art_verifier/art_verifier.cc @@ -112,6 +112,9 @@ struct MethodVerifierArgs : public CmdlineArgs { } else if (option.starts_with("--repetitions=")) { char* end; repetitions_ = strtoul(option.substr(strlen("--repetitions=")).data(), &end, 10); + } else if (option.starts_with("--api-level=")) { + char* end; + api_level_ = strtoul(option.substr(strlen("--api-level=")).data(), &end, 10); } else { return kParseUnknownArgument; } @@ -147,6 +150,7 @@ struct MethodVerifierArgs : public CmdlineArgs { " --verbose: use verbose verifier mode.\n" " --verbose-debug: use verbose verifier debug mode.\n" " --repetitions=<count>: repeat the verification count times.\n" + " --api-level=<level>: use API level for verification.\n" "\n"; usage += Base::GetUsage(); @@ -163,6 +167,8 @@ struct MethodVerifierArgs : public CmdlineArgs { bool method_verifier_verbose_debug_ = false; size_t repetitions_ = 0u; + + uint32_t api_level_ = 0u; }; struct MethodVerifierMain : public CmdlineMain<MethodVerifierArgs> { @@ -242,6 +248,7 @@ struct MethodVerifierMain : public CmdlineMain<MethodVerifierArgs> { runtime->GetCompilerCallbacks(), true, verifier::HardFailLogMode::kLogWarning, + args_->api_level_, &error_msg); if (args_->repetitions_ == 0) { LOG(INFO) << descriptor << ": " << res << " " << error_msg; |