#include "vdex_file.h"
#include "verifier/method_verifier.h"
#include "verifier/method_verifier-inl.h"
-#include "verifier/verifier_log_mode.h"
#include "verifier/verifier_deps.h"
+#include "verifier/verifier_enums.h"
namespace art {
hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::Class> klass(
hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor, class_loader)));
- verifier::MethodVerifier::FailureKind failure_kind;
+ verifier::FailureKind failure_kind;
if (klass == nullptr) {
CHECK(soa.Self()->IsExceptionPending());
soa.Self()->ClearException();
true /* allow soft failures */,
log_level_,
&error_msg);
- if (failure_kind == verifier::MethodVerifier::kHardFailure) {
+ if (failure_kind == verifier::FailureKind::kHardFailure) {
LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
<< " because: " << error_msg;
manager_->GetCompiler()->SetHadHardVerifierFailure();
// Force a soft failure for the VerifierDeps. This is a sanity measure, as
// the vdex file already records that the class hasn't been resolved. It avoids
// trying to do future verification optimizations when processing the vdex file.
- DCHECK(failure_kind == verifier::MethodVerifier::kSoftFailure ||
- failure_kind == verifier::MethodVerifier::kNoFailure)
+ DCHECK(failure_kind == verifier::FailureKind::kSoftFailure ||
+ failure_kind == verifier::FailureKind::kNoFailure)
<< failure_kind;
- failure_kind = verifier::MethodVerifier::kSoftFailure;
+ failure_kind = verifier::FailureKind::kSoftFailure;
}
} else if (!SkipClass(jclass_loader, dex_file, klass.Get())) {
CHECK(klass->IsResolved()) << klass->PrettyClass();
<< " failed to fully verify: state= " << klass->GetStatus();
}
if (klass->IsVerified()) {
- DCHECK_EQ(failure_kind, verifier::MethodVerifier::kNoFailure);
+ DCHECK_EQ(failure_kind, verifier::FailureKind::kNoFailure);
} else if (klass->ShouldVerifyAtRuntime()) {
- DCHECK_EQ(failure_kind, verifier::MethodVerifier::kSoftFailure);
+ DCHECK_EQ(failure_kind, verifier::FailureKind::kSoftFailure);
} else {
- DCHECK_EQ(failure_kind, verifier::MethodVerifier::kHardFailure);
+ DCHECK_EQ(failure_kind, verifier::FailureKind::kHardFailure);
}
}
} else {
// Make the skip a soft failure, essentially being considered as verify at runtime.
- failure_kind = verifier::MethodVerifier::kSoftFailure;
+ failure_kind = verifier::FailureKind::kSoftFailure;
}
verifier::VerifierDeps::MaybeRecordVerificationStatus(
dex_file, class_def.class_idx_, failure_kind);
#include "type_lookup_table.h"
#include "utils/dex_cache_arrays_layout-inl.h"
#include "vdex_file.h"
-#include "verifier/method_verifier.h"
#include "verifier/verifier_deps.h"
#include "zip_archive.h"
#include "ssa_liveness_analysis.h"
#include "ssa_phi_elimination.h"
#include "utils/assembler.h"
-#include "verifier/method_verifier.h"
+#include "verifier/verifier_compiler_binding.h"
namespace art {
const VerifiedMethod* verified_method = compiler_driver->GetVerifiedMethod(&dex_file, method_idx);
DCHECK(!verified_method->HasRuntimeThrow());
if (compiler_driver->IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file)
- || verifier::MethodVerifier::CanCompilerHandleVerificationFailure(
+ || verifier::CanCompilerHandleVerificationFailure(
verified_method->GetEncounteredVerificationFailures())) {
ArenaAllocator arena(Runtime::Current()->GetArenaPool());
CodeVectorAllocator code_allocator(&arena);
#include "driver/compiler_options.h"
#include "driver/compiler_driver.h"
#include "handle_scope-inl.h"
-#include "verifier/method_verifier-inl.h"
+#include "indenter.h"
#include "mirror/class_loader.h"
#include "runtime.h"
-#include "thread.h"
#include "scoped_thread_state_change-inl.h"
+#include "thread.h"
#include "utils/atomic_method_ref_map-inl.h"
+#include "verifier/method_verifier-inl.h"
namespace art {
namespace verifier {
"thread.h",
"thread_state.h",
"ti/agent.h",
- "verifier/method_verifier.h",
+ "verifier/verifier_enums.h",
],
output_extension: "operator_out.cc",
}
}
}
-verifier::MethodVerifier::FailureKind ClassLinker::VerifyClass(
+verifier::FailureKind ClassLinker::VerifyClass(
Thread* self, Handle<mirror::Class> klass, verifier::HardFailLogMode log_level) {
{
// TODO: assert that the monitor on the Class is held
// this class as a parent to another.
if (klass->IsErroneous()) {
ThrowEarlierClassFailure(klass.Get());
- return verifier::MethodVerifier::kHardFailure;
+ return verifier::FailureKind::kHardFailure;
}
// Don't attempt to re-verify if already verified.
if (klass->IsVerified()) {
EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
- return verifier::MethodVerifier::kNoFailure;
+ return verifier::FailureKind::kNoFailure;
}
// For AOT, don't attempt to re-verify if we have already found we should
// verify at runtime.
if (Runtime::Current()->IsAotCompiler() && klass->ShouldVerifyAtRuntime()) {
- return verifier::MethodVerifier::kSoftFailure;
+ return verifier::FailureKind::kSoftFailure;
}
if (klass->GetStatus() == mirror::Class::kStatusResolved) {
if (!Runtime::Current()->IsVerificationEnabled()) {
mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self);
EnsureSkipAccessChecksMethods(klass, image_pointer_size_);
- return verifier::MethodVerifier::kNoFailure;
+ return verifier::FailureKind::kNoFailure;
}
}
// If we have a superclass and we get a hard verification failure we can return immediately.
if (supertype != nullptr && !AttemptSupertypeVerification(self, klass, supertype)) {
CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
- return verifier::MethodVerifier::kHardFailure;
+ return verifier::FailureKind::kHardFailure;
}
// Verify all default super-interfaces.
} else if (UNLIKELY(!AttemptSupertypeVerification(self, klass, iface))) {
// We had a hard failure while verifying this interface. Just return immediately.
CHECK(self->IsExceptionPending()) << "Verification error should be pending.";
- return verifier::MethodVerifier::kHardFailure;
+ return verifier::FailureKind::kHardFailure;
} else if (UNLIKELY(!iface->IsVerified())) {
// We softly failed to verify the iface. Stop checking and clean up.
// Put the iface into the supertype handle so we know what caused us to fail.
DCHECK(!mirror::Class::IsErroneous(oat_file_class_status) || !preverified);
std::string error_msg;
- verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
+ verifier::FailureKind verifier_failure = verifier::FailureKind::kNoFailure;
if (!preverified) {
Runtime* runtime = Runtime::Current();
verifier_failure = verifier::MethodVerifier::VerifyClass(self,
// Verification is done, grab the lock again.
ObjectLock<mirror::Class> lock(self, klass);
- if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
- if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) {
+ if (preverified || verifier_failure != verifier::FailureKind::kHardFailure) {
+ if (!preverified && verifier_failure != verifier::FailureKind::kNoFailure) {
VLOG(class_linker) << "Soft verification failure in class "
<< klass->PrettyDescriptor()
<< " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
self->AssertNoPendingException();
// Make sure all classes referenced by catch blocks are resolved.
ResolveClassExceptionHandlerTypes(klass);
- if (verifier_failure == verifier::MethodVerifier::kNoFailure) {
+ if (verifier_failure == verifier::FailureKind::kNoFailure) {
// Even though there were no verifier failures we need to respect whether the super-class and
// super-default-interfaces were verified or requiring runtime reverification.
if (supertype == nullptr || supertype->IsVerified()) {
CHECK_EQ(supertype->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime);
mirror::Class::SetStatus(klass, mirror::Class::kStatusRetryVerificationAtRuntime, self);
// Pretend a soft failure occurred so that we don't consider the class verified below.
- verifier_failure = verifier::MethodVerifier::kSoftFailure;
+ verifier_failure = verifier::FailureKind::kSoftFailure;
}
} else {
- CHECK_EQ(verifier_failure, verifier::MethodVerifier::kSoftFailure);
+ CHECK_EQ(verifier_failure, verifier::FailureKind::kSoftFailure);
// Soft failures at compile time should be retried at runtime. Soft
// failures at runtime will be handled by slow paths in the generated
// code. Set status accordingly.
ThrowVerifyError(klass.Get(), "%s", error_msg.c_str());
mirror::Class::SetStatus(klass, mirror::Class::kStatusErrorResolved, self);
}
- if (preverified || verifier_failure == verifier::MethodVerifier::kNoFailure) {
+ if (preverified || verifier_failure == verifier::FailureKind::kNoFailure) {
// Class is verified so we don't need to do any access check on its methods.
// Let the interpreter know it by setting the kAccSkipAccessChecks flag onto each
// method.
#include <utility>
#include <vector>
-#include "base/allocator.h"
#include "base/enums.h"
-#include "base/hash_set.h"
#include "base/macros.h"
#include "base/mutex.h"
#include "class_table.h"
#include "jni.h"
#include "mirror/class.h"
#include "object_callbacks.h"
-#include "verifier/method_verifier.h"
-#include "verifier/verifier_log_mode.h"
+#include "verifier/verifier_enums.h"
namespace art {
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
- verifier::MethodVerifier::FailureKind VerifyClass(
+ verifier::FailureKind VerifyClass(
Thread* self,
Handle<mirror::Class> klass,
verifier::HardFailLogMode log_level = verifier::HardFailLogMode::kLogNone)
#include "reflection.h"
#include "reflection-inl.h"
#include "stack.h"
-#include "verifier/method_verifier.h"
#include "well_known_classes.h"
namespace art {
#include "ti_class_loader.h"
#include "transform.h"
#include "verifier/method_verifier.h"
-#include "verifier/verifier_log_mode.h"
+#include "verifier/verifier_enums.h"
namespace openjdkjvmti {
art::StackHandleScope<2> hs(driver_->self_);
std::string error;
// TODO Make verification log level lower
- art::verifier::MethodVerifier::FailureKind failure =
+ art::verifier::FailureKind failure =
art::verifier::MethodVerifier::VerifyClass(driver_->self_,
dex_file_.get(),
hs.NewHandle(iter.GetNewDexCache()),
/*log_level*/
art::verifier::HardFailLogMode::kLogWarning,
&error);
- bool passes = failure == art::verifier::MethodVerifier::kNoFailure;
+ bool passes = failure == art::verifier::FailureKind::kNoFailure;
if (!passes) {
RecordFailure(ERR(FAILS_VERIFICATION), "Failed to verify class. Error was: " + error);
}
#include "oat_quick_method_header.h"
#include "stack.h"
#include "stack_map.h"
-#include "verifier/method_verifier.h"
namespace art {
#ifndef ART_RUNTIME_RUNTIME_OPTIONS_H_
#define ART_RUNTIME_RUNTIME_OPTIONS_H_
-#include "base/variant_map.h"
-#include "cmdline_types.h" // TODO: don't need to include this file here
-
-// Map keys
#include <vector>
#include <string>
+
+#include <stdio.h>
+#include <stdarg.h>
+
#include "base/logging.h"
+#include "base/variant_map.h"
+#include "cmdline_types.h" // TODO: don't need to include this file here
#include "jdwp/jdwp.h"
#include "jit/jit.h"
#include "jit/jit_code_cache.h"
#include "gc/space/large_object_space.h"
#include "arch/instruction_set.h"
#include "jit/profile_saver_options.h"
-#include "verifier/verify_mode.h"
-#include <stdio.h>
-#include <stdarg.h>
+#include "verifier/verifier_enums.h"
namespace art {
#include "dex_instruction_visitor.h"
#include "experimental_flags.h"
#include "gc/accounting/card_table-inl.h"
+#include "handle_scope-inl.h"
#include "indenter.h"
#include "intern_table.h"
#include "leb128.h"
#include "scoped_thread_state_change-inl.h"
#include "utils.h"
#include "verifier_deps.h"
-#include "handle_scope-inl.h"
+#include "verifier_compiler_binding.h"
namespace art {
namespace verifier {
reg_line->MarkAllRegistersAsConflicts(verifier);
}
-MethodVerifier::FailureKind MethodVerifier::VerifyClass(Thread* self,
- mirror::Class* klass,
- CompilerCallbacks* callbacks,
- bool allow_soft_failures,
- HardFailLogMode log_level,
- std::string* error) {
+FailureKind MethodVerifier::VerifyClass(Thread* self,
+ mirror::Class* klass,
+ CompilerCallbacks* callbacks,
+ bool allow_soft_failures,
+ HardFailLogMode log_level,
+ std::string* error) {
if (klass->IsVerified()) {
- return kNoFailure;
+ return FailureKind::kNoFailure;
}
bool early_failure = false;
std::string failure_message;
ClassReference ref(&dex_file, klass->GetDexClassDefIndex());
callbacks->ClassRejected(ref);
}
- return kHardFailure;
+ return FailureKind::kHardFailure;
}
StackHandleScope<2> hs(self);
Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
return kDirect ? it->HasNextDirectMethod() : it->HasNextVirtualMethod();
}
-static MethodVerifier::FailureKind FailureKindMax(MethodVerifier::FailureKind fk1,
- MethodVerifier::FailureKind fk2) {
- static_assert(MethodVerifier::FailureKind::kNoFailure <
- MethodVerifier::FailureKind::kSoftFailure
- && MethodVerifier::FailureKind::kSoftFailure <
- MethodVerifier::FailureKind::kHardFailure,
+static FailureKind FailureKindMax(FailureKind fk1, FailureKind fk2) {
+ static_assert(FailureKind::kNoFailure < FailureKind::kSoftFailure
+ && FailureKind::kSoftFailure < FailureKind::kHardFailure,
"Unexpected FailureKind order");
return std::max(fk1, fk2);
}
log_level,
need_precise_constants,
&hard_failure_msg);
- if (result.kind == kHardFailure) {
- if (failure_data.kind == kHardFailure) {
+ if (result.kind == FailureKind::kHardFailure) {
+ if (failure_data.kind == FailureKind::kHardFailure) {
// If we logged an error before, we need a newline.
*error_string += "\n";
} else {
return failure_data;
}
-MethodVerifier::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) {
+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) {
ScopedTrace trace(__FUNCTION__);
// A class must not be abstract and final.
*error = "Verifier rejected class ";
*error += PrettyDescriptor(dex_file->GetClassDescriptor(class_def));
*error += ": class is abstract and final.";
- return kHardFailure;
+ return FailureKind::kHardFailure;
}
const uint8_t* class_data = dex_file->GetClassData(class_def);
if (class_data == nullptr) {
// empty class, probably a marker interface
- return kNoFailure;
+ return FailureKind::kNoFailure;
}
ClassDataItemIterator it(*dex_file, class_data);
while (it.HasNextStaticField() || it.HasNextInstanceField()) {
data1.Merge(data2);
- if (data1.kind == kNoFailure) {
- return kNoFailure;
+ if (data1.kind == FailureKind::kNoFailure) {
+ return FailureKind::kNoFailure;
} else {
if ((data1.types & VERIFY_ERROR_LOCKING) != 0) {
// Print a warning about expected slow-down. Use a string temporary to print one contiguous
verifier.DumpFailures(VLOG_STREAM(verifier) << "Soft verification failures in "
<< dex_file->PrettyMethod(method_idx) << "\n");
}
- result.kind = kSoftFailure;
+ result.kind = FailureKind::kSoftFailure;
if (method != nullptr &&
!CanCompilerHandleVerificationFailure(verifier.encountered_failure_types_)) {
method->SetDontCompile();
// code is valid (even the dead and unverified one). As such this is done only for apps.
// (CompilerDriver DCHECKs in VerifyClassVisitor that methods from boot image are
// fully verified).
- result.kind = kSoftFailure;
+ result.kind = FailureKind::kSoftFailure;
}
}
if ((verifier.encountered_failure_types_ & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
if (UNLIKELY(verifier.have_pending_experimental_failure_)) {
// Failed due to being forced into interpreter. This is ok because
// we just want to skip verification.
- result.kind = kSoftFailure;
+ result.kind = FailureKind::kSoftFailure;
} else {
CHECK(verifier.have_pending_hard_failure_);
if (VLOG_IS_ON(verifier)) {
*hard_failure_msg =
verifier.failure_messages_[verifier.failure_messages_.size() - 1]->str();
}
- result.kind = kHardFailure;
+ result.kind = FailureKind::kHardFailure;
if (callbacks != nullptr) {
// Let the interested party know that we failed the class.
#include "method_reference.h"
#include "register_line.h"
#include "reg_type_cache.h"
-#include "verifier_log_mode.h"
+#include "verifier_enums.h"
namespace art {
using RegisterLineArenaUniquePtr = std::unique_ptr<RegisterLine, RegisterLineArenaDelete>;
class RegType;
-/*
- * "Direct" and "virtual" methods are stored independently. The type of call used to invoke the
- * method determines which list we search, and whether we travel up into superclasses.
- *
- * (<clinit>, <init>, and methods declared "private" or "static" are stored in the "direct" list.
- * All others are stored in the "virtual" list.)
- */
-enum MethodType {
- METHOD_UNKNOWN = 0,
- METHOD_DIRECT, // <init>, private
- METHOD_STATIC, // static
- METHOD_VIRTUAL, // virtual
- METHOD_SUPER, // super
- METHOD_INTERFACE, // interface
- METHOD_POLYMORPHIC // polymorphic
-};
-std::ostream& operator<<(std::ostream& os, const MethodType& rhs);
-
-/*
- * An enumeration of problems that can turn up during verification.
- * Both VERIFY_ERROR_BAD_CLASS_SOFT and VERIFY_ERROR_BAD_CLASS_HARD denote failures that cause
- * the entire class to be rejected. However, VERIFY_ERROR_BAD_CLASS_SOFT denotes a soft failure
- * that can potentially be corrected, and the verifier will try again at runtime.
- * VERIFY_ERROR_BAD_CLASS_HARD denotes a hard failure that can't be corrected, and will cause
- * the class to remain uncompiled. Other errors denote verification errors that cause bytecode
- * to be rewritten to fail at runtime.
- */
-enum VerifyError {
- VERIFY_ERROR_BAD_CLASS_HARD = 1, // VerifyError; hard error that skips compilation.
- VERIFY_ERROR_BAD_CLASS_SOFT = 2, // VerifyError; soft error that verifies again at runtime.
-
- VERIFY_ERROR_NO_CLASS = 4, // NoClassDefFoundError.
- VERIFY_ERROR_NO_FIELD = 8, // NoSuchFieldError.
- VERIFY_ERROR_NO_METHOD = 16, // NoSuchMethodError.
- VERIFY_ERROR_ACCESS_CLASS = 32, // IllegalAccessError.
- VERIFY_ERROR_ACCESS_FIELD = 64, // IllegalAccessError.
- VERIFY_ERROR_ACCESS_METHOD = 128, // IllegalAccessError.
- VERIFY_ERROR_CLASS_CHANGE = 256, // IncompatibleClassChangeError.
- VERIFY_ERROR_INSTANTIATION = 512, // InstantiationError.
- // For opcodes that don't have complete verifier support, we need a way to continue
- // execution at runtime without attempting to re-verify (since we know it will fail no
- // matter what). Instead, run as the interpreter in a special "do access checks" mode
- // which will perform verifier-like checking on the fly.
- VERIFY_ERROR_FORCE_INTERPRETER = 1024, // Skip the verification phase at runtime;
- // force the interpreter to do access checks.
- // (sets a soft fail at compile time).
- VERIFY_ERROR_LOCKING = 2048, // Could not guarantee balanced locking. This should be
- // punted to the interpreter with access checks.
-};
-std::ostream& operator<<(std::ostream& os, const VerifyError& rhs);
-
// 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 +
// type-precise register analysis).
// The verifier
class MethodVerifier {
public:
- enum FailureKind {
- kNoFailure,
- kSoftFailure,
- kHardFailure,
- };
-
- static bool CanCompilerHandleVerificationFailure(uint32_t encountered_failure_types) {
- constexpr uint32_t unresolved_mask = verifier::VerifyError::VERIFY_ERROR_NO_CLASS
- | verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS
- | verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD
- | verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD;
- return (encountered_failure_types & (~unresolved_mask)) == 0;
- }
-
// Verify a class. Returns "kNoFailure" on success.
static FailureKind VerifyClass(Thread* self,
mirror::Class* klass,
// Verification result for method(s). Includes a (maximum) failure kind, and (the union of)
// all failure types.
struct FailureData : ValueObject {
- FailureKind kind = kNoFailure;
+ FailureKind kind = FailureKind::kNoFailure;
uint32_t types = 0U;
// Merge src into this. Uses the most severe failure kind, and the union of types.
DISALLOW_COPY_AND_ASSIGN(MethodVerifier);
};
-std::ostream& operator<<(std::ostream& os, const MethodVerifier::FailureKind& rhs);
} // namespace verifier
} // namespace art
#include "dex_file-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "utils.h"
-#include "verifier_log_mode.h"
+#include "verifier_enums.h"
namespace art {
namespace verifier {
// Verify the class
std::string error_msg;
- MethodVerifier::FailureKind failure = MethodVerifier::VerifyClass(
+ FailureKind failure = MethodVerifier::VerifyClass(
self, klass, nullptr, true, HardFailLogMode::kLogWarning, &error_msg);
if (android::base::StartsWith(descriptor, "Ljava/lang/invoke")) {
- ASSERT_TRUE(failure == MethodVerifier::kSoftFailure ||
- failure == MethodVerifier::kNoFailure) << error_msg;
+ ASSERT_TRUE(failure == FailureKind::kSoftFailure ||
+ failure == FailureKind::kNoFailure) << error_msg;
} else {
- ASSERT_TRUE(failure == MethodVerifier::kNoFailure) << error_msg;
+ ASSERT_TRUE(failure == FailureKind::kNoFailure) << error_msg;
}
}
--- /dev/null
+/*
+ * 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_VERIFIER_COMPILER_BINDING_H_
+#define ART_RUNTIME_VERIFIER_VERIFIER_COMPILER_BINDING_H_
+
+#include <inttypes.h>
+
+#include "base/macros.h"
+#include "verifier_enums.h"
+
+namespace art {
+namespace verifier {
+
+ALWAYS_INLINE
+static inline bool CanCompilerHandleVerificationFailure(uint32_t encountered_failure_types) {
+ constexpr uint32_t unresolved_mask = verifier::VerifyError::VERIFY_ERROR_NO_CLASS
+ | verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS
+ | verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD
+ | verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD;
+ return (encountered_failure_types & (~unresolved_mask)) == 0;
+}
+
+} // namespace verifier
+} // namespace art
+
+#endif // ART_RUNTIME_VERIFIER_VERIFIER_COMPILER_BINDING_H_
#include "base/stl_util.h"
#include "compiler_callbacks.h"
#include "dex_file-inl.h"
+#include "indenter.h"
#include "leb128.h"
#include "mirror/class-inl.h"
+#include "mirror/class_loader.h"
#include "obj_ptr-inl.h"
#include "runtime.h"
void VerifierDeps::MaybeRecordVerificationStatus(const DexFile& dex_file,
dex::TypeIndex type_idx,
- MethodVerifier::FailureKind failure_kind) {
- if (failure_kind == MethodVerifier::kNoFailure) {
+ FailureKind failure_kind) {
+ if (failure_kind == FailureKind::kNoFailure) {
// We only record classes that did not fully verify at compile time.
return;
}
#include <set>
#include <vector>
-#include "art_field.h"
-#include "art_method.h"
#include "base/array_ref.h"
#include "base/mutex.h"
-#include "indenter.h"
+#include "handle.h"
#include "method_resolution_kind.h"
-#include "method_verifier.h" // For MethodVerifier::FailureKind.
#include "obj_ptr.h"
-#include "os.h"
+#include "thread.h"
+#include "verifier_enums.h" // For MethodVerifier::FailureKind.
namespace art {
+
+class ArtField;
+class ArtMethod;
+class DexFile;
+class VariableIndentationOutputStream;
+
+namespace mirror {
+class Class;
+class ClassLoader;
+}
+
namespace verifier {
// Verification dependencies collector class used by the MethodVerifier to record
// Record the verification status of the class at `type_idx`.
static void MaybeRecordVerificationStatus(const DexFile& dex_file,
dex::TypeIndex type_idx,
- MethodVerifier::FailureKind failure_kind)
+ FailureKind failure_kind)
REQUIRES(!Locks::verifier_deps_lock_);
// Record the outcome `klass` of resolving type `type_idx` from `dex_file`.
--- /dev/null
+/*
+ * Copyright (C) 2015 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_VERIFIER_ENUMS_H_
+#define ART_RUNTIME_VERIFIER_VERIFIER_ENUMS_H_
+
+#include <stdint.h>
+
+namespace art {
+namespace verifier {
+
+// The mode that the verifier should run as.
+enum class VerifyMode : int8_t {
+ kNone, // Everything is assumed verified.
+ kEnable, // Standard verification, try pre-verifying at compile-time.
+ kSoftFail, // Force a soft fail, punting to the interpreter with access checks.
+};
+
+// The outcome of verification.
+enum class FailureKind {
+ kNoFailure,
+ kSoftFailure,
+ kHardFailure,
+};
+std::ostream& operator<<(std::ostream& os, const FailureKind& rhs);
+
+// How to log hard failures during verification.
+enum class HardFailLogMode {
+ kLogNone, // Don't log hard failures at all.
+ kLogVerbose, // Log with severity VERBOSE.
+ kLogWarning, // Log with severity WARNING.
+ kLogInternalFatal, // Log with severity FATAL_WITHOUT_ABORT
+};
+
+/*
+ * "Direct" and "virtual" methods are stored independently. The type of call used to invoke the
+ * method determines which list we search, and whether we travel up into superclasses.
+ *
+ * (<clinit>, <init>, and methods declared "private" or "static" are stored in the "direct" list.
+ * All others are stored in the "virtual" list.)
+ */
+enum MethodType {
+ METHOD_UNKNOWN = 0,
+ METHOD_DIRECT, // <init>, private
+ METHOD_STATIC, // static
+ METHOD_VIRTUAL, // virtual
+ METHOD_SUPER, // super
+ METHOD_INTERFACE, // interface
+ METHOD_POLYMORPHIC // polymorphic
+};
+std::ostream& operator<<(std::ostream& os, const MethodType& rhs);
+
+/*
+ * An enumeration of problems that can turn up during verification.
+ * Both VERIFY_ERROR_BAD_CLASS_SOFT and VERIFY_ERROR_BAD_CLASS_HARD denote failures that cause
+ * the entire class to be rejected. However, VERIFY_ERROR_BAD_CLASS_SOFT denotes a soft failure
+ * that can potentially be corrected, and the verifier will try again at runtime.
+ * VERIFY_ERROR_BAD_CLASS_HARD denotes a hard failure that can't be corrected, and will cause
+ * the class to remain uncompiled. Other errors denote verification errors that cause bytecode
+ * to be rewritten to fail at runtime.
+ */
+enum VerifyError {
+ VERIFY_ERROR_BAD_CLASS_HARD = 1, // VerifyError; hard error that skips compilation.
+ VERIFY_ERROR_BAD_CLASS_SOFT = 2, // VerifyError; soft error that verifies again at runtime.
+
+ VERIFY_ERROR_NO_CLASS = 4, // NoClassDefFoundError.
+ VERIFY_ERROR_NO_FIELD = 8, // NoSuchFieldError.
+ VERIFY_ERROR_NO_METHOD = 16, // NoSuchMethodError.
+ VERIFY_ERROR_ACCESS_CLASS = 32, // IllegalAccessError.
+ VERIFY_ERROR_ACCESS_FIELD = 64, // IllegalAccessError.
+ VERIFY_ERROR_ACCESS_METHOD = 128, // IllegalAccessError.
+ VERIFY_ERROR_CLASS_CHANGE = 256, // IncompatibleClassChangeError.
+ VERIFY_ERROR_INSTANTIATION = 512, // InstantiationError.
+ // For opcodes that don't have complete verifier support, we need a way to continue
+ // execution at runtime without attempting to re-verify (since we know it will fail no
+ // matter what). Instead, run as the interpreter in a special "do access checks" mode
+ // which will perform verifier-like checking on the fly.
+ VERIFY_ERROR_FORCE_INTERPRETER = 1024, // Skip the verification phase at runtime;
+ // force the interpreter to do access checks.
+ // (sets a soft fail at compile time).
+ VERIFY_ERROR_LOCKING = 2048, // Could not guarantee balanced locking. This should be
+ // punted to the interpreter with access checks.
+};
+std::ostream& operator<<(std::ostream& os, const VerifyError& rhs);
+
+} // namespace verifier
+} // namespace art
+
+#endif // ART_RUNTIME_VERIFIER_VERIFIER_ENUMS_H_
+++ /dev/null
-/*
- * Copyright (C) 2016 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_VERIFIER_LOG_MODE_H_
-#define ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
-
-namespace art {
-namespace verifier {
-
-enum class HardFailLogMode {
- kLogNone, // Don't log hard failures at all.
- kLogVerbose, // Log with severity VERBOSE.
- kLogWarning, // Log with severity WARNING.
- kLogInternalFatal, // Log with severity FATAL_WITHOUT_ABORT
-};
-
-} // namespace verifier
-} // namespace art
-
-#endif // ART_RUNTIME_VERIFIER_VERIFIER_LOG_MODE_H_
+++ /dev/null
-/*
- * Copyright (C) 2015 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_VERIFY_MODE_H_
-#define ART_RUNTIME_VERIFIER_VERIFY_MODE_H_
-
-#include <stdint.h>
-
-namespace art {
-namespace verifier {
-
-// The mode that the verifier should run as.
-enum class VerifyMode : int8_t {
- kNone, // Everything is assumed verified.
- kEnable, // Standard verification, try pre-verifying at compile-time.
- kSoftFail, // Force a soft fail, punting to the interpreter with access checks.
-};
-
-} // namespace verifier
-} // namespace art
-
-#endif // ART_RUNTIME_VERIFIER_VERIFY_MODE_H_