ART: Add API level to verifier
Pass API level to verifier. In preparation for API-level dependent
checks.
Bug: 111969862
Test: m test-art-host
Change-Id: I700ef52e28436a7fda8b9d9ef29841110ed6d3bb
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 6eca304..3f28aa7 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1886,7 +1886,9 @@
class VerifyClassVisitor : public CompilationVisitor {
public:
VerifyClassVisitor(const ParallelCompilationManager* manager, verifier::HardFailLogMode log_level)
- : manager_(manager), log_level_(log_level) {}
+ : manager_(manager),
+ log_level_(log_level),
+ sdk_version_(Runtime::Current()->GetTargetSdkVersion()) {}
virtual void Visit(size_t class_def_index) REQUIRES(!Locks::mutator_lock_) OVERRIDE {
ScopedTrace trace(__FUNCTION__);
@@ -1923,6 +1925,7 @@
Runtime::Current()->GetCompilerCallbacks(),
true /* allow soft failures */,
log_level_,
+ sdk_version_,
&error_msg);
if (failure_kind == verifier::FailureKind::kHardFailure) {
LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
@@ -1995,6 +1998,7 @@
private:
const ParallelCompilationManager* const manager_;
const verifier::HardFailLogMode log_level_;
+ const uint32_t sdk_version_;
};
void CompilerDriver::VerifyDexFile(jobject class_loader,
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index c223549..5d76329 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -178,7 +178,8 @@
true /* allow_soft_failures */,
true /* need_precise_constants */,
false /* verify to dump */,
- true /* allow_thread_suspension */);
+ true /* allow_thread_suspension */,
+ 0 /* api_level */);
verifier.Verify();
soa.Self()->SetVerifierDeps(nullptr);
has_failures = verifier.HasFailures();
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index a5cc38b..b6bfec6 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -1474,7 +1474,7 @@
}
return verifier::MethodVerifier::VerifyMethodAndDump(
soa.Self(), vios, dex_method_idx, dex_file, dex_cache, *options_.class_loader_,
- class_def, code_item, method, method_access_flags);
+ class_def, code_item, method, method_access_flags, /* api_level */ 0);
}
return nullptr;
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index 8707e27..f8c1172 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -1122,6 +1122,7 @@
true, /*allow_soft_failures*/
/*log_level*/
art::verifier::HardFailLogMode::kLogWarning,
+ art::Runtime::Current()->GetTargetSdkVersion(),
&error);
switch (failure) {
case art::verifier::FailureKind::kNoFailure:
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f80d34c..bc28a66 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -4169,6 +4169,7 @@
runtime->GetCompilerCallbacks(),
runtime->IsAotCompiler(),
log_level,
+ Runtime::Current()->GetTargetSdkVersion(),
error_msg);
}
diff --git a/runtime/monitor.cc b/runtime/monitor.cc
index d47bc0d..7eabe1d 100644
--- a/runtime/monitor.cc
+++ b/runtime/monitor.cc
@@ -1401,7 +1401,10 @@
// Ask the verifier for the dex pcs of all the monitor-enter instructions corresponding to
// the locks held in this stack frame.
std::vector<verifier::MethodVerifier::DexLockInfo> monitor_enter_dex_pcs;
- verifier::MethodVerifier::FindLocksAtDexPc(m, dex_pc, &monitor_enter_dex_pcs);
+ verifier::MethodVerifier::FindLocksAtDexPc(m,
+ dex_pc,
+ &monitor_enter_dex_pcs,
+ Runtime::Current()->GetTargetSdkVersion());
for (verifier::MethodVerifier::DexLockInfo& dex_lock_info : monitor_enter_dex_pcs) {
// As a debug check, check that dex PC corresponds to a monitor-enter.
if (kIsDebugBuild) {
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index a1b8938..2064fc4 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -149,6 +149,7 @@
CompilerCallbacks* callbacks,
bool allow_soft_failures,
HardFailLogMode log_level,
+ uint32_t api_level,
std::string* error) {
if (klass->IsVerified()) {
return FailureKind::kNoFailure;
@@ -188,6 +189,7 @@
callbacks,
allow_soft_failures,
log_level,
+ api_level,
error);
}
@@ -211,6 +213,7 @@
CompilerCallbacks* callbacks,
bool allow_soft_failures,
HardFailLogMode log_level,
+ uint32_t api_level,
std::string* error) {
// A class must not be abstract and final.
if ((class_def.access_flags_ & (kAccAbstract | kAccFinal)) == (kAccAbstract | kAccFinal)) {
@@ -261,6 +264,7 @@
allow_soft_failures,
log_level,
/*need_precise_constants*/ false,
+ api_level,
&hard_failure_msg);
if (result.kind == FailureKind::kHardFailure) {
if (failure_data.kind == FailureKind::kHardFailure) {
@@ -322,6 +326,7 @@
bool allow_soft_failures,
HardFailLogMode log_level,
bool need_precise_constants,
+ uint32_t api_level,
std::string* hard_failure_msg) {
MethodVerifier::FailureData result;
uint64_t start_ns = kTimeVerifyMethod ? NanoTime() : 0;
@@ -339,7 +344,8 @@
allow_soft_failures,
need_precise_constants,
false /* verify to dump */,
- true /* allow_thread_suspension */);
+ true /* allow_thread_suspension */,
+ api_level);
if (verifier.Verify()) {
// Verification completed, however failures may be pending that didn't cause the verification
// to hard fail.
@@ -458,7 +464,8 @@
const DexFile::ClassDef& class_def,
const DexFile::CodeItem* code_item,
ArtMethod* method,
- uint32_t method_access_flags) {
+ uint32_t method_access_flags,
+ uint32_t api_level) {
MethodVerifier* verifier = new MethodVerifier(self,
dex_file,
dex_cache,
@@ -472,7 +479,8 @@
true /* allow_soft_failures */,
true /* need_precise_constants */,
true /* verify_to_dump */,
- true /* allow_thread_suspension */);
+ true /* allow_thread_suspension */,
+ api_level);
verifier->Verify();
verifier->DumpFailures(vios->Stream());
vios->Stream() << verifier->info_messages_.str();
@@ -500,7 +508,8 @@
bool allow_soft_failures,
bool need_precise_constants,
bool verify_to_dump,
- bool allow_thread_suspension)
+ bool allow_thread_suspension,
+ uint32_t api_level)
: self_(self),
arena_stack_(Runtime::Current()->GetArenaPool()),
allocator_(&arena_stack_),
@@ -534,7 +543,8 @@
verify_to_dump_(verify_to_dump),
allow_thread_suspension_(allow_thread_suspension),
is_constructor_(false),
- link_(nullptr) {
+ link_(nullptr),
+ api_level_(api_level == 0 ? std::numeric_limits<uint32_t>::max() : api_level) {
self->PushVerifier(this);
}
@@ -546,7 +556,8 @@
void MethodVerifier::FindLocksAtDexPc(
ArtMethod* m,
uint32_t dex_pc,
- std::vector<MethodVerifier::DexLockInfo>* monitor_enter_dex_pcs) {
+ std::vector<MethodVerifier::DexLockInfo>* monitor_enter_dex_pcs,
+ uint32_t api_level) {
StackHandleScope<2> hs(Thread::Current());
Handle<mirror::DexCache> dex_cache(hs.NewHandle(m->GetDexCache()));
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(m->GetClassLoader()));
@@ -563,7 +574,8 @@
true /* allow_soft_failures */,
false /* need_precise_constants */,
false /* verify_to_dump */,
- false /* allow_thread_suspension */);
+ false /* allow_thread_suspension */,
+ api_level);
verifier.interesting_dex_pc_ = dex_pc;
verifier.monitor_enter_dex_pcs_ = monitor_enter_dex_pcs;
verifier.FindLocksAtDexPc();
diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h
index 9890af9..eef2280 100644
--- a/runtime/verifier/method_verifier.h
+++ b/runtime/verifier/method_verifier.h
@@ -100,6 +100,7 @@
CompilerCallbacks* callbacks,
bool allow_soft_failures,
HardFailLogMode log_level,
+ uint32_t api_level,
std::string* error)
REQUIRES_SHARED(Locks::mutator_lock_);
static FailureKind VerifyClass(Thread* self,
@@ -110,6 +111,7 @@
CompilerCallbacks* callbacks,
bool allow_soft_failures,
HardFailLogMode log_level,
+ uint32_t api_level,
std::string* error)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -121,7 +123,8 @@
Handle<mirror::ClassLoader> class_loader,
const DexFile::ClassDef& class_def,
const DexFile::CodeItem* code_item, ArtMethod* method,
- uint32_t method_access_flags)
+ uint32_t method_access_flags,
+ uint32_t api_level)
REQUIRES_SHARED(Locks::mutator_lock_);
uint8_t EncodePcToReferenceMapData() const;
@@ -163,8 +166,10 @@
// Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding
// to the locks held at 'dex_pc' in method 'm'.
// Note: this is the only situation where the verifier will visit quickened instructions.
- static void FindLocksAtDexPc(ArtMethod* m, uint32_t dex_pc,
- std::vector<DexLockInfo>* monitor_enter_dex_pcs)
+ static void FindLocksAtDexPc(ArtMethod* m,
+ uint32_t dex_pc,
+ std::vector<DexLockInfo>* monitor_enter_dex_pcs,
+ uint32_t api_level)
REQUIRES_SHARED(Locks::mutator_lock_);
static void Init() REQUIRES_SHARED(Locks::mutator_lock_);
@@ -242,7 +247,8 @@
bool allow_soft_failures,
bool need_precise_constants,
bool verify_to_dump,
- bool allow_thread_suspension)
+ bool allow_thread_suspension,
+ uint32_t api_level)
REQUIRES_SHARED(Locks::mutator_lock_);
void UninstantiableError(const char* descriptor);
@@ -299,6 +305,7 @@
bool allow_soft_failures,
HardFailLogMode log_level,
bool need_precise_constants,
+ uint32_t api_level,
std::string* hard_failure_msg)
REQUIRES_SHARED(Locks::mutator_lock_);
@@ -790,6 +797,10 @@
// Link, for the method verifier root linked list.
MethodVerifier* link_;
+ // API level, for dependent checks. Note: we do not use '0' for unset here, to simplify checks.
+ // Instead, unset level should correspond to max().
+ const uint32_t api_level_;
+
friend class art::Thread;
friend class VerifierDepsTest;
diff --git a/runtime/verifier/method_verifier_test.cc b/runtime/verifier/method_verifier_test.cc
index d1be9fa..cedc583 100644
--- a/runtime/verifier/method_verifier_test.cc
+++ b/runtime/verifier/method_verifier_test.cc
@@ -42,7 +42,7 @@
// Verify the class
std::string error_msg;
FailureKind failure = MethodVerifier::VerifyClass(
- self, klass, nullptr, true, HardFailLogMode::kLogWarning, &error_msg);
+ self, klass, nullptr, true, HardFailLogMode::kLogWarning, /* api_level */ 0u, &error_msg);
if (android::base::StartsWith(descriptor, "Ljava/lang/invoke")) {
ASSERT_TRUE(failure == FailureKind::kSoftFailure ||
diff --git a/tools/art_verifier/art_verifier.cc b/tools/art_verifier/art_verifier.cc
index fc62410..1a76a86 100644
--- a/tools/art_verifier/art_verifier.cc
+++ b/tools/art_verifier/art_verifier.cc
@@ -112,6 +112,9 @@
} else if (option.starts_with("--repetitions=")) {
char* end;
repetitions_ = strtoul(option.substr(strlen("--repetitions=")).data(), &end, 10);
+ } else if (option.starts_with("--api-level=")) {
+ char* end;
+ api_level_ = strtoul(option.substr(strlen("--api-level=")).data(), &end, 10);
} else {
return kParseUnknownArgument;
}
@@ -147,6 +150,7 @@
" --verbose: use verbose verifier mode.\n"
" --verbose-debug: use verbose verifier debug mode.\n"
" --repetitions=<count>: repeat the verification count times.\n"
+ " --api-level=<level>: use API level for verification.\n"
"\n";
usage += Base::GetUsage();
@@ -163,6 +167,8 @@
bool method_verifier_verbose_debug_ = false;
size_t repetitions_ = 0u;
+
+ uint32_t api_level_ = 0u;
};
struct MethodVerifierMain : public CmdlineMain<MethodVerifierArgs> {
@@ -242,6 +248,7 @@
runtime->GetCompilerCallbacks(),
true,
verifier::HardFailLogMode::kLogWarning,
+ args_->api_level_,
&error_msg);
if (args_->repetitions_ == 0) {
LOG(INFO) << descriptor << ": " << res << " " << error_msg;