ART: Add ClassVerifier
Remove class handling from MethodVerifier.
Test: m test-art-host
Change-Id: I0e125e0c8a852936ed7cff0f349a7fde97f62826
diff --git a/dex2oat/dex/dex_to_dex_decompiler_test.cc b/dex2oat/dex/dex_to_dex_decompiler_test.cc
index b5525dc..9d65436 100644
--- a/dex2oat/dex/dex_to_dex_decompiler_test.cc
+++ b/dex2oat/dex/dex_to_dex_decompiler_test.cc
@@ -31,7 +31,6 @@
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
#include "thread.h"
-#include "verifier/method_verifier-inl.h"
#include "verifier/verifier_deps.h"
namespace art {
diff --git a/dex2oat/dex/quick_compiler_callbacks.cc b/dex2oat/dex/quick_compiler_callbacks.cc
index c277f03..f6f8267 100644
--- a/dex2oat/dex/quick_compiler_callbacks.cc
+++ b/dex2oat/dex/quick_compiler_callbacks.cc
@@ -19,10 +19,6 @@
#include "dex/verification_results.h"
#include "driver/compiler_driver.h"
#include "mirror/class-inl.h"
-#include "mirror/object.h"
-#include "obj_ptr-inl.h"
-#include "thread-current-inl.h"
-#include "verifier/method_verifier-inl.h"
namespace art {
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index b73a7d8..520b455 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -85,8 +85,7 @@
#include "utils/dex_cache_arrays_layout-inl.h"
#include "utils/swap_space.h"
#include "vdex_file.h"
-#include "verifier/method_verifier-inl.h"
-#include "verifier/method_verifier.h"
+#include "verifier/class_verifier.h"
#include "verifier/verifier_deps.h"
#include "verifier/verifier_enums.h"
@@ -1884,16 +1883,16 @@
soa.Self(), dex_file)));
std::string error_msg;
failure_kind =
- verifier::MethodVerifier::VerifyClass(soa.Self(),
- &dex_file,
- dex_cache,
- class_loader,
- class_def,
- Runtime::Current()->GetCompilerCallbacks(),
- true /* allow soft failures */,
- log_level_,
- sdk_version_,
- &error_msg);
+ verifier::ClassVerifier::VerifyClass(soa.Self(),
+ &dex_file,
+ dex_cache,
+ class_loader,
+ class_def,
+ 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)
<< " because: " << error_msg;
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index e51ae4d..b500130 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -80,7 +80,7 @@
#include "ti_breakpoint.h"
#include "ti_class_loader.h"
#include "transform.h"
-#include "verifier/method_verifier.h"
+#include "verifier/class_verifier.h"
#include "verifier/verifier_enums.h"
namespace openjdkjvmti {
@@ -1119,17 +1119,17 @@
std::string error;
// TODO Make verification log level lower
art::verifier::FailureKind failure =
- art::verifier::MethodVerifier::VerifyClass(driver_->self_,
- dex_file_.get(),
- hs.NewHandle(iter.GetNewDexCache()),
- hs.NewHandle(GetClassLoader()),
- /*class_def=*/ dex_file_->GetClassDef(0),
- /*callbacks=*/ nullptr,
- /*allow_soft_failures=*/ true,
- /*log_level=*/
- art::verifier::HardFailLogMode::kLogWarning,
- art::Runtime::Current()->GetTargetSdkVersion(),
- &error);
+ art::verifier::ClassVerifier::VerifyClass(driver_->self_,
+ dex_file_.get(),
+ hs.NewHandle(iter.GetNewDexCache()),
+ hs.NewHandle(GetClassLoader()),
+ /*class_def=*/ dex_file_->GetClassDef(0),
+ /*callbacks=*/ nullptr,
+ /*allow_soft_failures=*/ true,
+ /*log_level=*/
+ art::verifier::HardFailLogMode::kLogWarning,
+ art::Runtime::Current()->GetTargetSdkVersion(),
+ &error);
switch (failure) {
case art::verifier::FailureKind::kNoFailure:
case art::verifier::FailureKind::kSoftFailure:
diff --git a/runtime/Android.bp b/runtime/Android.bp
index 2170e95..56c84a6 100644
--- a/runtime/Android.bp
+++ b/runtime/Android.bp
@@ -203,6 +203,7 @@
"transaction.cc",
"var_handles.cc",
"vdex_file.cc",
+ "verifier/class_verifier.cc",
"verifier/instruction_flags.cc",
"verifier/method_verifier.cc",
"verifier/reg_type.cc",
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e5dcc0d..4364590 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -133,7 +133,7 @@
#include "thread_list.h"
#include "trace.h"
#include "utils/dex_cache_arrays_layout-inl.h"
-#include "verifier/method_verifier.h"
+#include "verifier/class_verifier.h"
#include "well_known_classes.h"
namespace art {
@@ -900,7 +900,7 @@
// initialize the StackOverflowError class (as it might require running the verifier). Instead,
// ensure that the class will be initialized.
if (kMemoryToolIsAvailable && !Runtime::Current()->IsAotCompiler()) {
- verifier::MethodVerifier::Init(); // Need to prepare the verifier.
+ verifier::ClassVerifier::Init(); // Need to prepare the verifier.
ObjPtr<mirror::Class> soe_klass = FindSystemClass(self, "Ljava/lang/StackOverflowError;");
if (soe_klass == nullptr || !EnsureInitialized(self, hs.NewHandle(soe_klass), true, true)) {
@@ -4608,13 +4608,13 @@
verifier::HardFailLogMode log_level,
std::string* error_msg) {
Runtime* const runtime = Runtime::Current();
- return verifier::MethodVerifier::VerifyClass(self,
- klass.Get(),
- runtime->GetCompilerCallbacks(),
- runtime->IsAotCompiler(),
- log_level,
- Runtime::Current()->GetTargetSdkVersion(),
- error_msg);
+ return verifier::ClassVerifier::VerifyClass(self,
+ klass.Get(),
+ runtime->GetCompilerCallbacks(),
+ runtime->IsAotCompiler(),
+ log_level,
+ Runtime::Current()->GetTargetSdkVersion(),
+ error_msg);
}
bool ClassLinker::VerifyClassUsingOatFile(const DexFile& dex_file,
diff --git a/runtime/common_throws.cc b/runtime/common_throws.cc
index 499bf28..a1168af 100644
--- a/runtime/common_throws.cc
+++ b/runtime/common_throws.cc
@@ -35,8 +35,6 @@
#include "nativehelper/scoped_local_ref.h"
#include "obj_ptr-inl.h"
#include "thread.h"
-#include "vdex_file.h"
-#include "verifier/method_verifier.h"
#include "well_known_classes.h"
namespace art {
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 0d32e0b..d698d48 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -162,7 +162,7 @@
#include "trace.h"
#include "transaction.h"
#include "vdex_file.h"
-#include "verifier/method_verifier.h"
+#include "verifier/class_verifier.h"
#include "well_known_classes.h"
#ifdef ART_TARGET_ANDROID
@@ -464,7 +464,7 @@
delete oat_file_manager_;
Thread::Shutdown();
QuasiAtomic::Shutdown();
- verifier::MethodVerifier::Shutdown();
+ verifier::ClassVerifier::Shutdown();
// Destroy allocators before shutting down the MemMap because they may use it.
java_vm_.reset();
@@ -1541,7 +1541,7 @@
CHECK(class_linker_ != nullptr);
- verifier::MethodVerifier::Init();
+ verifier::ClassVerifier::Init();
if (runtime_options.Exists(Opt::MethodTrace)) {
trace_config_.reset(new TraceConfig());
@@ -2096,7 +2096,7 @@
.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
pre_allocated_NoClassDefFoundError_.VisitRootIfNonNull(visitor, RootInfo(kRootVMInternal));
VisitImageRoots(visitor);
- verifier::MethodVerifier::VisitStaticRoots(visitor);
+ verifier::ClassVerifier::VisitStaticRoots(visitor);
VisitTransactionRoots(visitor);
}
diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc
new file mode 100644
index 0000000..649fb11
--- /dev/null
+++ b/runtime/verifier/class_verifier.cc
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "class_verifier.h"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+
+#include "art_method-inl.h"
+#include "base/systrace.h"
+#include "base/utils.h"
+#include "class_linker.h"
+#include "compiler_callbacks.h"
+#include "dex/class_accessor-inl.h"
+#include "dex/class_reference.h"
+#include "dex/descriptors_names.h"
+#include "dex/dex_file-inl.h"
+#include "handle_scope-inl.h"
+#include "method_verifier-inl.h"
+#include "mirror/class-inl.h"
+#include "mirror/dex_cache.h"
+#include "runtime.h"
+
+namespace art {
+namespace verifier {
+
+using android::base::StringPrintf;
+
+// We print a warning blurb about "dx --no-optimize" when we find monitor-locking issues. Make
+// sure we only print this once.
+static bool gPrintedDxMonitorText = false;
+
+FailureKind ClassVerifier::VerifyClass(Thread* self,
+ ObjPtr<mirror::Class> klass,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ uint32_t api_level,
+ std::string* error) {
+ if (klass->IsVerified()) {
+ return FailureKind::kNoFailure;
+ }
+ bool early_failure = false;
+ std::string failure_message;
+ const DexFile& dex_file = klass->GetDexFile();
+ const dex::ClassDef* class_def = klass->GetClassDef();
+ ObjPtr<mirror::Class> super = klass->GetSuperClass();
+ std::string temp;
+ if (super == nullptr && strcmp("Ljava/lang/Object;", klass->GetDescriptor(&temp)) != 0) {
+ early_failure = true;
+ failure_message = " that has no super class";
+ } else if (super != nullptr && super->IsFinal()) {
+ early_failure = true;
+ failure_message = " that attempts to sub-class final class " + super->PrettyDescriptor();
+ } else if (class_def == nullptr) {
+ early_failure = true;
+ failure_message = " that isn't present in dex file " + dex_file.GetLocation();
+ }
+ if (early_failure) {
+ *error = "Verifier rejected class " + klass->PrettyDescriptor() + failure_message;
+ if (callbacks != nullptr) {
+ ClassReference ref(&dex_file, klass->GetDexClassDefIndex());
+ callbacks->ClassRejected(ref);
+ }
+ return FailureKind::kHardFailure;
+ }
+ StackHandleScope<2> hs(self);
+ Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
+ Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
+ return VerifyClass(self,
+ &dex_file,
+ dex_cache,
+ class_loader,
+ *class_def,
+ callbacks,
+ allow_soft_failures,
+ log_level,
+ api_level,
+ error);
+}
+
+FailureKind ClassVerifier::VerifyClass(Thread* self,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const dex::ClassDef& class_def,
+ 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)) {
+ *error = "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ": class is abstract and final.";
+ return FailureKind::kHardFailure;
+ }
+
+ ClassAccessor accessor(*dex_file, class_def);
+ SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(accessor.GetDescriptor());
+
+ int64_t previous_method_idx[2] = { -1, -1 };
+ MethodVerifier::FailureData failure_data;
+ ClassLinker* const linker = Runtime::Current()->GetClassLinker();
+
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
+ self->AllowThreadSuspension();
+ const uint32_t method_idx = method.GetIndex();
+ if (method_idx == *previous_idx) {
+ // smali can create dex files with two encoded_methods sharing the same method_idx
+ // http://code.google.com/p/smali/issues/detail?id=119
+ continue;
+ }
+ *previous_idx = method_idx;
+ const InvokeType type = method.GetInvokeType(class_def.access_flags_);
+ ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
+ method_idx, dex_cache, class_loader, /* referrer= */ nullptr, type);
+ if (resolved_method == nullptr) {
+ DCHECK(self->IsExceptionPending());
+ // We couldn't resolve the method, but continue regardless.
+ self->ClearException();
+ } else {
+ DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
+ }
+ std::string hard_failure_msg;
+ MethodVerifier::FailureData result =
+ MethodVerifier::VerifyMethod(self,
+ method_idx,
+ dex_file,
+ dex_cache,
+ class_loader,
+ class_def,
+ method.GetCodeItem(),
+ resolved_method,
+ method.GetAccessFlags(),
+ callbacks,
+ 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) {
+ // If we logged an error before, we need a newline.
+ *error += "\n";
+ } else {
+ // If we didn't log a hard failure before, print the header of the message.
+ *error += "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ":";
+ }
+ *error += " ";
+ *error += hard_failure_msg;
+ }
+ failure_data.Merge(result);
+ }
+
+ if (failure_data.kind == FailureKind::kNoFailure) {
+ return FailureKind::kNoFailure;
+ } else {
+ if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
+ // Print a warning about expected slow-down. Use a string temporary to print one contiguous
+ // warning.
+ std::string tmp =
+ StringPrintf("Class %s failed lock verification and will run slower.",
+ PrettyDescriptor(accessor.GetDescriptor()).c_str());
+ if (!gPrintedDxMonitorText) {
+ tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
+ "and incorrect proguard optimizations.";
+ gPrintedDxMonitorText = true;
+ }
+ LOG(WARNING) << tmp;
+ }
+ return failure_data.kind;
+ }
+}
+
+void ClassVerifier::Init() {
+ MethodVerifier::Init();
+}
+
+void ClassVerifier::Shutdown() {
+ MethodVerifier::Shutdown();
+}
+
+void ClassVerifier::VisitStaticRoots(RootVisitor* visitor) {
+ MethodVerifier::VisitStaticRoots(visitor);
+}
+
+} // namespace verifier
+} // namespace art
diff --git a/runtime/verifier/class_verifier.h b/runtime/verifier/class_verifier.h
new file mode 100644
index 0000000..b7d3850
--- /dev/null
+++ b/runtime/verifier/class_verifier.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_VERIFIER_CLASS_VERIFIER_H_
+#define ART_RUNTIME_VERIFIER_CLASS_VERIFIER_H_
+
+#include <string>
+
+#include <android-base/macros.h>
+#include <android-base/thread_annotations.h>
+
+#include "base/locks.h"
+#include "handle.h"
+#include "obj_ptr.h"
+#include "verifier_enums.h"
+
+namespace art {
+
+class CompilerCallbacks;
+class DexFile;
+class RootVisitor;
+class Thread;
+
+namespace dex {
+struct ClassDef;
+} // namespace dex
+
+namespace mirror {
+class Class;
+class DexCache;
+class ClassLoader;
+} // namespace mirror
+
+namespace verifier {
+
+// Verifier that ensures the complete class is OK.
+class ClassVerifier {
+ public:
+ // Verify a class. Returns "kNoFailure" on success.
+ static FailureKind VerifyClass(Thread* self,
+ ObjPtr<mirror::Class> klass,
+ 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,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const dex::ClassDef& class_def,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ uint32_t api_level,
+ std::string* error)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ static void Init() REQUIRES_SHARED(Locks::mutator_lock_);
+ static void Shutdown();
+
+ static void VisitStaticRoots(RootVisitor* visitor)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ClassVerifier);
+};
+
+} // namespace verifier
+} // namespace art
+
+#endif // ART_RUNTIME_VERIFIER_CLASS_VERIFIER_H_
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 91eba21..f32dd73 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -73,10 +73,6 @@
// On VLOG(verifier), should we dump the whole state when we run into a hard failure?
static constexpr bool kDumpRegLinesOnHardFailureIfVLOG = true;
-// We print a warning blurb about "dx --no-optimize" when we find monitor-locking issues. Make
-// sure we only print this once.
-static bool gPrintedDxMonitorText = false;
-
PcToRegisterLineTable::PcToRegisterLineTable(ScopedArenaAllocator& allocator)
: register_lines_(allocator.Adapter(kArenaAllocVerifier)) {}
@@ -145,55 +141,6 @@
reg_line->MarkAllRegistersAsConflicts(verifier);
}
-FailureKind MethodVerifier::VerifyClass(Thread* self,
- ObjPtr<mirror::Class> klass,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- uint32_t api_level,
- std::string* error) {
- if (klass->IsVerified()) {
- return FailureKind::kNoFailure;
- }
- bool early_failure = false;
- std::string failure_message;
- const DexFile& dex_file = klass->GetDexFile();
- const dex::ClassDef* class_def = klass->GetClassDef();
- ObjPtr<mirror::Class> super = klass->GetSuperClass();
- std::string temp;
- if (super == nullptr && strcmp("Ljava/lang/Object;", klass->GetDescriptor(&temp)) != 0) {
- early_failure = true;
- failure_message = " that has no super class";
- } else if (super != nullptr && super->IsFinal()) {
- early_failure = true;
- failure_message = " that attempts to sub-class final class " + super->PrettyDescriptor();
- } else if (class_def == nullptr) {
- early_failure = true;
- failure_message = " that isn't present in dex file " + dex_file.GetLocation();
- }
- if (early_failure) {
- *error = "Verifier rejected class " + klass->PrettyDescriptor() + failure_message;
- if (callbacks != nullptr) {
- ClassReference ref(&dex_file, klass->GetDexClassDefIndex());
- callbacks->ClassRejected(ref);
- }
- return FailureKind::kHardFailure;
- }
- StackHandleScope<2> hs(self);
- Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
- Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
- return VerifyClass(self,
- &dex_file,
- dex_cache,
- class_loader,
- *class_def,
- callbacks,
- allow_soft_failures,
- log_level,
- api_level,
- error);
-}
-
static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) {
static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure
&& FailureKind::kSoftFailure < FailureKind::kHardFailure,
@@ -206,103 +153,6 @@
types |= fd.types;
}
-FailureKind MethodVerifier::VerifyClass(Thread* self,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const dex::ClassDef& class_def,
- 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)) {
- *error = "Verifier rejected class ";
- *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error += ": class is abstract and final.";
- return FailureKind::kHardFailure;
- }
-
- ClassAccessor accessor(*dex_file, class_def);
- SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(accessor.GetDescriptor());
-
- int64_t previous_method_idx[2] = { -1, -1 };
- MethodVerifier::FailureData failure_data;
- ClassLinker* const linker = Runtime::Current()->GetClassLinker();
-
- for (const ClassAccessor::Method& method : accessor.GetMethods()) {
- int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
- self->AllowThreadSuspension();
- const uint32_t method_idx = method.GetIndex();
- if (method_idx == *previous_idx) {
- // smali can create dex files with two encoded_methods sharing the same method_idx
- // http://code.google.com/p/smali/issues/detail?id=119
- continue;
- }
- *previous_idx = method_idx;
- const InvokeType type = method.GetInvokeType(class_def.access_flags_);
- ArtMethod* resolved_method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
- method_idx, dex_cache, class_loader, /* referrer= */ nullptr, type);
- if (resolved_method == nullptr) {
- DCHECK(self->IsExceptionPending());
- // We couldn't resolve the method, but continue regardless.
- self->ClearException();
- } else {
- DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
- }
- std::string hard_failure_msg;
- MethodVerifier::FailureData result = VerifyMethod(self,
- method_idx,
- dex_file,
- dex_cache,
- class_loader,
- class_def,
- method.GetCodeItem(),
- resolved_method,
- method.GetAccessFlags(),
- callbacks,
- 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) {
- // If we logged an error before, we need a newline.
- *error += "\n";
- } else {
- // If we didn't log a hard failure before, print the header of the message.
- *error += "Verifier rejected class ";
- *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error += ":";
- }
- *error += " ";
- *error += hard_failure_msg;
- }
- failure_data.Merge(result);
- }
-
- if (failure_data.kind == FailureKind::kNoFailure) {
- return FailureKind::kNoFailure;
- } else {
- if ((failure_data.types & VERIFY_ERROR_LOCKING) != 0) {
- // Print a warning about expected slow-down. Use a string temporary to print one contiguous
- // warning.
- std::string tmp =
- StringPrintf("Class %s failed lock verification and will run slower.",
- PrettyDescriptor(accessor.GetDescriptor()).c_str());
- if (!gPrintedDxMonitorText) {
- tmp = tmp + "\nCommon causes for lock verification issues are non-optimized dex code\n"
- "and incorrect proguard optimizations.";
- gPrintedDxMonitorText = true;
- }
- LOG(WARNING) << tmp;
- }
- return failure_data.kind;
- }
-}
-
static bool IsLargeMethod(const CodeItemDataAccessor& accessor) {
if (!accessor.HasCodeItem()) {
return false;
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index c178df0..92abe9b 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -99,27 +99,6 @@
// The verifier
class MethodVerifier {
public:
- // Verify a class. Returns "kNoFailure" on success.
- static FailureKind VerifyClass(Thread* self,
- ObjPtr<mirror::Class> klass,
- 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,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const dex::ClassDef& class_def,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- uint32_t api_level,
- std::string* error)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
static MethodVerifier* VerifyMethodAndDump(Thread* self,
VariableIndentationOutputStream* vios,
uint32_t method_idx,
@@ -807,6 +786,7 @@
const uint32_t api_level_;
friend class art::Thread;
+ friend class ClassVerifier;
friend class VerifierDepsTest;
DISALLOW_COPY_AND_ASSIGN(MethodVerifier);
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index 09171a4..e56cde9 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -23,6 +23,7 @@
#include "base/utils.h"
#include "class_linker-inl.h"
+#include "class_verifier.h"
#include "common_runtime_test.h"
#include "dex/dex_file-inl.h"
#include "scoped_thread_state_change-inl.h"
@@ -41,7 +42,7 @@
// Verify the class
std::string error_msg;
- FailureKind failure = MethodVerifier::VerifyClass(
+ FailureKind failure = ClassVerifier::VerifyClass(
self, klass, nullptr, true, HardFailLogMode::kLogWarning, /* api_level= */ 0u, &error_msg);
if (android::base::StartsWith(descriptor, "Ljava/lang/invoke")) {
diff --git a/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc
index b4aa678..6fe27d6 100644
--- a/tools/art_verifier/art_verifier.cc
+++ b/tools/art_verifier/art_verifier.cc
@@ -30,7 +30,7 @@
#include "mirror/dex_cache-inl.h"
#include "runtime.h"
#include "scoped_thread_state_change-inl.h"
-#include "verifier/method_verifier.h"
+#include "verifier/class_verifier.h"
#include "well_known_classes.h"
#include <sys/stat.h>
@@ -246,13 +246,13 @@
}
std::string error_msg;
verifier::FailureKind res =
- verifier::MethodVerifier::VerifyClass(soa.Self(),
- h_klass.Get(),
- runtime->GetCompilerCallbacks(),
- true,
- verifier::HardFailLogMode::kLogWarning,
- args_->api_level_,
- &error_msg);
+ verifier::ClassVerifier::VerifyClass(soa.Self(),
+ h_klass.Get(),
+ runtime->GetCompilerCallbacks(),
+ true,
+ verifier::HardFailLogMode::kLogWarning,
+ args_->api_level_,
+ &error_msg);
if (args_->repetitions_ == 0) {
LOG(INFO) << descriptor << ": " << res << " " << error_msg;
}