summaryrefslogtreecommitdiff
path: root/runtime/verifier/method_verifier.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/verifier/method_verifier.cc')
-rw-r--r--runtime/verifier/method_verifier.cc164
1 files changed, 51 insertions, 113 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index f57f757f0b..59617481eb 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -35,6 +35,7 @@
#include "class_linker.h"
#include "class_root.h"
#include "compiler_callbacks.h"
+#include "dex/class_accessor-inl.h"
#include "dex/descriptors_names.h"
#include "dex/dex_file-inl.h"
#include "dex/dex_file_exception_helpers.h"
@@ -190,11 +191,6 @@ FailureKind MethodVerifier::VerifyClass(Thread* self,
error);
}
-template <bool kDirect>
-static bool HasNextMethod(ClassDataItemIterator* it) {
- return kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod();
-}
-
static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) {
static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure
&& FailureKind::kSoftFailure < FailureKind::kHardFailure,
@@ -207,45 +203,51 @@ void MethodVerifier::FailureData::Merge(const MethodVerifier::FailureData& fd) {
types |= fd.types;
}
-template <bool kDirect>
-MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self,
- ClassLinker* linker,
- const DexFile* dex_file,
- const DexFile::ClassDef& class_def,
- ClassDataItemIterator* it,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- bool need_precise_constants,
- std::string* error_string) {
- DCHECK(it != nullptr);
+FailureKind MethodVerifier::VerifyClass(Thread* self,
+ const DexFile* dex_file,
+ Handle<mirror::DexCache> dex_cache,
+ Handle<mirror::ClassLoader> class_loader,
+ const DexFile::ClassDef& class_def,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ std::string* error) {
+ SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ // 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);
+
+ int64_t previous_method_idx[2] = { -1, -1 };
MethodVerifier::FailureData failure_data;
+ ClassLinker* const linker = Runtime::Current()->GetClassLinker();
- int64_t previous_method_idx = -1;
- while (HasNextMethod<kDirect>(it)) {
+ for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+ int64_t* previous_idx = &previous_method_idx[method.IsStaticOrDirect() ? 0u : 1u];
self->AllowThreadSuspension();
- uint32_t method_idx = it->GetMemberIndex();
- if (method_idx == previous_method_idx) {
+ 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
- it->Next();
continue;
}
- previous_method_idx = method_idx;
- InvokeType type = it->GetMethodInvokeType(class_def);
- ArtMethod* method = linker->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
+ *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 (method == nullptr) {
+ if (resolved_method == nullptr) {
DCHECK(self->IsExceptionPending());
// We couldn't resolve the method, but continue regardless.
self->ClearException();
} else {
- DCHECK(method->GetDeclaringClassUnchecked() != nullptr) << type;
+ DCHECK(resolved_method->GetDeclaringClassUnchecked() != nullptr) << type;
}
- StackHandleScope<1> hs(self);
std::string hard_failure_msg;
MethodVerifier::FailureData result = VerifyMethod(self,
method_idx,
@@ -253,99 +255,39 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethods(Thread* self,
dex_cache,
class_loader,
class_def,
- it->GetMethodCodeItem(),
- method,
- it->GetMethodAccessFlags(),
+ method.GetCodeItem(),
+ resolved_method,
+ method.GetAccessFlags(),
callbacks,
allow_soft_failures,
log_level,
- need_precise_constants,
+ /*need_precise_constants*/ false,
&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_string += "\n";
+ *error += "\n";
} else {
// If we didn't log a hard failure before, print the header of the message.
- *error_string += "Verifier rejected class ";
- *error_string += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
- *error_string += ":";
+ *error += "Verifier rejected class ";
+ *error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
+ *error += ":";
}
- *error_string += " ";
- *error_string += hard_failure_msg;
+ *error += " ";
+ *error += hard_failure_msg;
}
failure_data.Merge(result);
- it->Next();
- }
-
- return failure_data;
-}
-
-FailureKind MethodVerifier::VerifyClass(Thread* self,
- const DexFile* dex_file,
- Handle<mirror::DexCache> dex_cache,
- Handle<mirror::ClassLoader> class_loader,
- const DexFile::ClassDef& class_def,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- std::string* error) {
- SCOPED_TRACE << "VerifyClass " << PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
-
- // 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;
}
- const uint8_t* class_data = dex_file->GetClassData(class_def);
- if (class_data == nullptr) {
- // empty class, probably a marker interface
- return FailureKind::kNoFailure;
- }
- ClassDataItemIterator it(*dex_file, class_data);
- it.SkipAllFields();
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- // Direct methods.
- MethodVerifier::FailureData data1 = VerifyMethods<true>(self,
- linker,
- dex_file,
- class_def,
- &it,
- dex_cache,
- class_loader,
- callbacks,
- allow_soft_failures,
- log_level,
- false /* need precise constants */,
- error);
- // Virtual methods.
- MethodVerifier::FailureData data2 = VerifyMethods<false>(self,
- linker,
- dex_file,
- class_def,
- &it,
- dex_cache,
- class_loader,
- callbacks,
- allow_soft_failures,
- log_level,
- false /* need precise constants */,
- error);
-
- data1.Merge(data2);
-
- if (data1.kind == FailureKind::kNoFailure) {
+ if (failure_data.kind == FailureKind::kNoFailure) {
return FailureKind::kNoFailure;
} else {
- if ((data1.types & VERIFY_ERROR_LOCKING) != 0) {
+ 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(dex_file->GetClassDescriptor(class_def)).c_str());
+ 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.";
@@ -353,7 +295,7 @@ FailureKind MethodVerifier::VerifyClass(Thread* self,
}
LOG(WARNING) << tmp;
}
- return data1.kind;
+ return failure_data.kind;
}
}
@@ -1924,15 +1866,11 @@ bool MethodVerifier::CodeFlowVerifyMethod() {
static uint32_t GetFirstFinalInstanceFieldIndex(const DexFile& dex_file, dex::TypeIndex type_idx) {
const DexFile::ClassDef* class_def = dex_file.FindClassDef(type_idx);
DCHECK(class_def != nullptr);
- const uint8_t* class_data = dex_file.GetClassData(*class_def);
- DCHECK(class_data != nullptr);
- ClassDataItemIterator it(dex_file, class_data);
- it.SkipStaticFields();
- while (it.HasNextInstanceField()) {
- if ((it.GetFieldAccessFlags() & kAccFinal) != 0) {
- return it.GetMemberIndex();
- }
- it.Next();
+ ClassAccessor accessor(dex_file, *class_def);
+ for (const ClassAccessor::Field& field : accessor.GetInstanceFields()) {
+ if (field.IsFinal()) {
+ return field.GetIndex();
+ }
}
return dex::kDexNoIndex;
}