diff options
-rw-r--r-- | dex2oat/dex/dex_to_dex_decompiler_test.cc | 1 | ||||
-rw-r--r-- | dex2oat/dex/quick_compiler_callbacks.cc | 4 | ||||
-rw-r--r-- | dex2oat/driver/compiler_driver.cc | 23 | ||||
-rw-r--r-- | openjdkjvmti/ti_redefine.cc | 24 | ||||
-rw-r--r-- | runtime/Android.bp | 1 | ||||
-rw-r--r-- | runtime/class_linker.cc | 18 | ||||
-rw-r--r-- | runtime/common_throws.cc | 2 | ||||
-rw-r--r-- | runtime/runtime.cc | 8 | ||||
-rw-r--r-- | runtime/verifier/class_verifier.cc | 206 | ||||
-rw-r--r-- | runtime/verifier/class_verifier.h | 86 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 150 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 22 | ||||
-rw-r--r-- | runtime/verifier/method_verifier_test.cc | 3 | ||||
-rw-r--r-- | tools/art_verifier/art_verifier.cc | 16 |
14 files changed, 340 insertions, 224 deletions
diff --git a/dex2oat/dex/dex_to_dex_decompiler_test.cc b/dex2oat/dex/dex_to_dex_decompiler_test.cc index b5525dc6a4..9d65436959 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 c277f033d2..f6f82678c8 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 b73a7d8165..520b455a7a 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 @@ class VerifyClassVisitor : public CompilationVisitor { 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 e51ae4d255..b500130d7a 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 @@ bool Redefiner::ClassRedefinition::CheckVerification(const RedefinitionDataIter& 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 2170e95e63..56c84a6c17 100644 --- a/runtime/Android.bp +++ b/runtime/Android.bp @@ -203,6 +203,7 @@ libart_cc_defaults { "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 e5dcc0d989..43645903a5 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 @@ void ClassLinker::FinishInit(Thread* self) { // 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::FailureKind ClassLinker::PerformClassVerification(Thread* self, 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 499bf28451..a1168afd1c 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 0d32e0b17c..d698d4817b 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 @@ Runtime::~Runtime() { 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 @@ bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in) { 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 @@ void Runtime::VisitNonThreadRoots(RootVisitor* visitor) { .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 0000000000..649fb112d3 --- /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 0000000000..b7d38500cc --- /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 91eba2149b..f32dd739ad 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -73,10 +73,6 @@ static constexpr bool kTimeVerifyMethod = !kIsDebugBuild; // 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 @@ static void SafelyMarkAllRegistersAsConflicts(MethodVerifier* verifier, Register 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 @@ void MethodVerifier::FailureData::Merge(const MethodVerifier::FailureData& fd) { 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 c178df05a4..92abe9bd5d 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -99,27 +99,6 @@ class PcToRegisterLineTable { // 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 @@ class MethodVerifier { 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 09171a4342..e56cde9d41 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 @@ class MethodVerifierTest : public CommonRuntimeTest { // 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 b4aa6784c8..6fe27d659d 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 @@ struct MethodVerifierMain : public CmdlineMain<MethodVerifierArgs> { } 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; } |