summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Calin Juravle <calin@google.com> 2021-01-14 19:54:23 -0800
committer Calin Juravle <calin@google.com> 2021-01-21 00:33:57 +0000
commit2c2724cb36cd5a9cec6c852c681efc3b7c6b86ea (patch)
tree203b76db53f102d031e43ea0632194d4517d6bec
parent350c2ff41ff234c71b21f8e653e44be0e23504d9 (diff)
Disable the public SDK Checker during exception throwing
The compiler will try to throw exception when it cannot resolved methods/classes or when there's an incompatible class change. While doing so, it requires the thrown exception class to be initialized. However, when verifying with a public SDK Checker installed, it's possible that the exception class may not initialized due to private member access (e.g. serialVersionUid). Since during verification the exceptions are simply mechanism for the compiler to propagate the verification error it is OK to disable the SDK Checker and allow the class to be initialized. Bug: 177017481 Test: m test-art-host & manual Change-Id: I3765897bf9885b7e26b3ab044002df88866cd3cd
-rw-r--r--runtime/aot_class_linker.cc6
-rw-r--r--runtime/aot_class_linker.h1
-rw-r--r--runtime/class_linker.cc6
-rw-r--r--runtime/class_linker.h8
-rw-r--r--runtime/scoped_disable_public_sdk_checker.h46
-rw-r--r--runtime/sdk_checker.cc14
-rw-r--r--runtime/sdk_checker.h5
-rw-r--r--runtime/thread.cc11
8 files changed, 93 insertions, 4 deletions
diff --git a/runtime/aot_class_linker.cc b/runtime/aot_class_linker.cc
index b11c08d4e5..505946646d 100644
--- a/runtime/aot_class_linker.cc
+++ b/runtime/aot_class_linker.cc
@@ -262,4 +262,10 @@ bool AotClassLinker::DenyAccessBasedOnPublicSdk(const char* type_descriptor) con
return sdk_checker_ != nullptr && sdk_checker_->ShouldDenyAccess(type_descriptor);
}
+void AotClassLinker::SetEnablePublicSdkChecks(bool enabled) {
+ if (sdk_checker_ != nullptr) {
+ sdk_checker_->SetEnabled(enabled);
+ }
+}
+
} // namespace art
diff --git a/runtime/aot_class_linker.h b/runtime/aot_class_linker.h
index 30a79aa489..a094e3a174 100644
--- a/runtime/aot_class_linker.h
+++ b/runtime/aot_class_linker.h
@@ -46,6 +46,7 @@ static bool CanReferenceInBootImageExtension(ObjPtr<mirror::Class> klass, gc::He
bool DenyAccessBasedOnPublicSdk(ArtField* art_field ATTRIBUTE_UNUSED) const override
REQUIRES_SHARED(Locks::mutator_lock_);
bool DenyAccessBasedOnPublicSdk(const char* type_descriptor ATTRIBUTE_UNUSED) const override;
+ void SetEnablePublicSdkChecks(bool enabled) override;
protected:
// Overridden version of PerformClassVerification allows skipping verification if the class was
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 8982368af4..f396a0a84a 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -9920,6 +9920,12 @@ bool ClassLinker::DenyAccessBasedOnPublicSdk(const char* type_descriptor ATTRIBU
UNREACHABLE();
}
+void ClassLinker::SetEnablePublicSdkChecks(bool enabled ATTRIBUTE_UNUSED) {
+ // Should not be called on ClassLinker, only on AotClassLinker that overrides this.
+ LOG(FATAL) << "UNREACHABLE";
+ UNREACHABLE();
+}
+
// Instantiate ClassLinker::ResolveMethod.
template ArtMethod* ClassLinker::ResolveMethod<ClassLinker::ResolveMode::kCheckICCEAndIAE>(
uint32_t method_idx,
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 94d19995c1..050b02a42f 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -825,13 +825,15 @@ class ClassLinker {
REQUIRES(!Locks::dex_lock_, !Roles::uninterruptible_);
// Verifies if the method is accesible according to the SdkChecker (if installed).
- virtual bool DenyAccessBasedOnPublicSdk(ArtMethod* art_method ATTRIBUTE_UNUSED) const
+ virtual bool DenyAccessBasedOnPublicSdk(ArtMethod* art_method) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Verifies if the field is accesible according to the SdkChecker (if installed).
- virtual bool DenyAccessBasedOnPublicSdk(ArtField* art_field ATTRIBUTE_UNUSED) const
+ virtual bool DenyAccessBasedOnPublicSdk(ArtField* art_field) const
REQUIRES_SHARED(Locks::mutator_lock_);
// Verifies if the descriptor is accesible according to the SdkChecker (if installed).
- virtual bool DenyAccessBasedOnPublicSdk(const char* type_descriptor ATTRIBUTE_UNUSED) const;
+ virtual bool DenyAccessBasedOnPublicSdk(const char* type_descriptor) const;
+ // Enable or disable public sdk checks.
+ virtual void SetEnablePublicSdkChecks(bool enabled);
protected:
virtual bool InitializeClass(Thread* self,
diff --git a/runtime/scoped_disable_public_sdk_checker.h b/runtime/scoped_disable_public_sdk_checker.h
new file mode 100644
index 0000000000..4ec1af3fa4
--- /dev/null
+++ b/runtime/scoped_disable_public_sdk_checker.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2021 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_SCOPED_DISABLE_PUBLIC_SDK_CHECKER_H_
+#define ART_RUNTIME_SCOPED_DISABLE_PUBLIC_SDK_CHECKER_H_
+
+#include "class_linker.h"
+
+namespace art {
+
+// Utility class to disabled the public sdk checker within a scope (if installed).
+class ScopedDisablePublicSdkChecker : public ValueObject {
+ public:
+ ALWAYS_INLINE ScopedDisablePublicSdkChecker() {
+ Runtime* runtime = Runtime::Current();
+ if (UNLIKELY(runtime->IsAotCompiler())) {
+ runtime->GetClassLinker()->SetEnablePublicSdkChecks(false);
+ }
+ }
+
+ ALWAYS_INLINE ~ScopedDisablePublicSdkChecker() {
+ Runtime* runtime = Runtime::Current();
+ if (UNLIKELY(runtime->IsAotCompiler())) {
+ runtime->GetClassLinker()->SetEnablePublicSdkChecks(true);
+ }
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedDisablePublicSdkChecker);
+};
+
+} // namespace art
+
+#endif // ART_RUNTIME_SCOPED_DISABLE_PUBLIC_SDK_CHECKER_H_
diff --git a/runtime/sdk_checker.cc b/runtime/sdk_checker.cc
index 22c43058e4..1dbe39c32e 100644
--- a/runtime/sdk_checker.cc
+++ b/runtime/sdk_checker.cc
@@ -23,7 +23,7 @@
namespace art {
-SdkChecker::SdkChecker() {}
+SdkChecker::SdkChecker() : enabled_(true) {}
SdkChecker* SdkChecker::Create(
const std::string& public_sdk, std::string* error_msg) {
@@ -47,6 +47,10 @@ SdkChecker* SdkChecker::Create(
}
bool SdkChecker::ShouldDenyAccess(ArtMethod* art_method) const {
+ if (!enabled_) {
+ return false;
+ }
+
bool found = false;
for (const std::unique_ptr<const DexFile>& dex_file : sdk_dex_files_) {
const dex::TypeId* declaring_type_id =
@@ -89,6 +93,10 @@ bool SdkChecker::ShouldDenyAccess(ArtMethod* art_method) const {
}
bool SdkChecker::ShouldDenyAccess(ArtField* art_field) const {
+ if (!enabled_) {
+ return false;
+ }
+
bool found = false;
for (const std::unique_ptr<const DexFile>& dex_file : sdk_dex_files_) {
std::string declaring_class;
@@ -123,6 +131,10 @@ bool SdkChecker::ShouldDenyAccess(ArtField* art_field) const {
}
bool SdkChecker::ShouldDenyAccess(const char* descriptor) const {
+ if (!enabled_) {
+ return false;
+ }
+
bool found = false;
for (const std::unique_ptr<const DexFile>& dex_file : sdk_dex_files_) {
const dex::TypeId* type_id = dex_file->FindTypeId(descriptor);
diff --git a/runtime/sdk_checker.h b/runtime/sdk_checker.h
index 29cb98d538..8d82237a60 100644
--- a/runtime/sdk_checker.h
+++ b/runtime/sdk_checker.h
@@ -60,10 +60,15 @@ class SdkChecker {
// Similar to ShouldDenyAccess(ArtMethod* art_method).
bool ShouldDenyAccess(const char* type_descriptor) const;
+ // Enabled/Disable the checks.
+ void SetEnabled(bool enabled) { enabled_ = enabled; }
+
private:
SdkChecker();
std::vector<std::unique_ptr<const DexFile>> sdk_dex_files_;
+
+ bool enabled_;
};
} // namespace art
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 645c51f73b..7f80691e54 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -104,6 +104,7 @@
#include "runtime.h"
#include "runtime_callbacks.h"
#include "scoped_thread_state_change-inl.h"
+#include "scoped_disable_public_sdk_checker.h"
#include "stack.h"
#include "stack_map.h"
#include "thread-inl.h"
@@ -3190,6 +3191,16 @@ void Thread::ThrowNewWrappedException(const char* exception_class_descriptor,
DCHECK_EQ(this, Thread::Current());
ScopedObjectAccessUnchecked soa(this);
StackHandleScope<3> hs(soa.Self());
+
+ // Disable public sdk checks if we need to throw exceptions.
+ // The checks are only used in AOT compilation and may block (exception) class
+ // initialization if it needs access to private fields (e.g. serialVersionUID).
+ //
+ // Since throwing an exception will EnsureInitialization and the public sdk may
+ // block that, disable the checks. It's ok to do so, because the thrown exceptions
+ // are not part of the application code that needs to verified.
+ ScopedDisablePublicSdkChecker sdpsc;
+
Handle<mirror::ClassLoader> class_loader(hs.NewHandle(GetCurrentClassLoader(soa.Self())));
ScopedLocalRef<jobject> cause(GetJniEnv(), soa.AddLocalReference<jobject>(GetException()));
ClearException();