Revert "Revert "Add "linkage" test options""
This reverts commit 91a8e6f60c508c6e010b6ef8e4056e3a6f04c447.
Reason for revert: Moved tests to gtest and under compilation only.
Change-Id: I60899694946353bfcd334473c20bb17c84f095e0
Bug: none
Test: make test-art-host-gtest-dex2oat_test
diff --git a/build/Android.gtest.mk b/build/Android.gtest.mk
index a40fc9e..cdea5c4 100644
--- a/build/Android.gtest.mk
+++ b/build/Android.gtest.mk
@@ -197,9 +197,15 @@
$(ART_TEST_TARGET_GTEST_VerifySoftFailDuringClinit_DEX): $(ART_TEST_GTEST_VerifySoftFailDuringClinit_SRC) $(HOST_OUT_EXECUTABLES)/smali
$(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
+# Linkage test artifacts.
+ART_TEST_GTEST_LinkageTest_SRC := $(abspath $(wildcard $(LOCAL_PATH)/LinkageTest/*.smali))
+ART_TEST_HOST_GTEST_LinkageTest_DEX := $(dir $(ART_TEST_HOST_GTEST_Main_DEX))$(subst Main,LinkageTest,$(basename $(notdir $(ART_TEST_HOST_GTEST_Main_DEX))))$(suffix $(ART_TEST_HOST_GTEST_Main_DEX))
+$(ART_TEST_HOST_GTEST_LinkageTest_DEX): $(ART_TEST_GTEST_LinkageTest_SRC) $(HOST_OUT_EXECUTABLES)/smali
+ $(HOST_OUT_EXECUTABLES)/smali assemble --output $@ $(filter %.smali,$^)
+
# Dex file dependencies for each gtest.
ART_GTEST_art_dex_file_loader_test_DEX_DEPS := GetMethodSignature Main Nested MultiDex
-ART_GTEST_dex2oat_environment_tests_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary MyClassNatives Nested VerifierDeps VerifierDepsMulti
+ART_GTEST_dex2oat_environment_tests_DEX_DEPS := Main MainStripped MultiDex MultiDexModifiedSecondary MyClassNatives Nested VerifierDeps VerifierDepsMulti LinkageTest
ART_GTEST_atomic_dex_ref_map_test_DEX_DEPS := Interfaces
ART_GTEST_class_linker_test_DEX_DEPS := AllFields ErroneousA ErroneousB ErroneousInit ForClassLoaderA ForClassLoaderB ForClassLoaderC ForClassLoaderD Interfaces MethodTypes MultiDex MyClass Nested Statics StaticsFromCode
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index cde6ae9..5681134 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -73,6 +73,8 @@
dump_cfg_file_name_(""),
dump_cfg_append_(false),
force_determinism_(false),
+ check_linkage_conditions_(false),
+ crash_on_linkage_violation_(false),
deduplicate_code_(true),
count_hotness_in_compiled_code_(false),
resolve_startup_const_strings_(false),
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index 79ba1c2..639c547 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -311,6 +311,14 @@
return force_determinism_;
}
+ bool IsCheckLinkageConditions() const {
+ return check_linkage_conditions_;
+ }
+
+ bool IsCrashOnLinkageViolation() const {
+ return crash_on_linkage_violation_;
+ }
+
bool DeduplicateCode() const {
return deduplicate_code_;
}
@@ -431,6 +439,13 @@
// outcomes.
bool force_determinism_;
+ // Whether the compiler should check for violation of the conditions required to perform AOT
+ // "linkage".
+ bool check_linkage_conditions_;
+ // Whether the compiler should crash when encountering a violation of one of
+ // the conditions required to perform AOT "linkage".
+ bool crash_on_linkage_violation_;
+
// Whether code should be deduplicated.
bool deduplicate_code_;
diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc
index ec05939..8e8fa80 100644
--- a/dex2oat/dex2oat.cc
+++ b/dex2oat/dex2oat.cc
@@ -806,7 +806,9 @@
app_image_fd_(kInvalidFd),
profile_file_fd_(kInvalidFd),
timings_(timings),
- force_determinism_(false)
+ force_determinism_(false),
+ check_linkage_conditions_(false),
+ crash_on_linkage_violation_(false)
{}
~Dex2Oat() {
@@ -1106,6 +1108,9 @@
}
compiler_options_->force_determinism_ = force_determinism_;
+ compiler_options_->check_linkage_conditions_ = check_linkage_conditions_;
+ compiler_options_->crash_on_linkage_violation_ = crash_on_linkage_violation_;
+
if (passes_to_run_filename_ != nullptr) {
passes_to_run_ = ReadCommentedInputFromFile<std::vector<std::string>>(
passes_to_run_filename_,
@@ -1324,6 +1329,8 @@
AssignIfExists(args, M::DirtyImageObjects, &dirty_image_objects_filename_);
AssignIfExists(args, M::ImageFormat, &image_storage_mode_);
AssignIfExists(args, M::CompilationReason, &compilation_reason_);
+ AssignTrueIfExists(args, M::CheckLinkageConditions, &check_linkage_conditions_);
+ AssignTrueIfExists(args, M::CrashOnLinkageViolation, &crash_on_linkage_violation_);
AssignIfExists(args, M::Backend, &compiler_kind_);
parser_options->requested_specific_compiler = args.Exists(M::Backend);
@@ -3016,6 +3023,10 @@
// See CompilerOptions.force_determinism_.
bool force_determinism_;
+ // See CompilerOptions.crash_on_linkage_violation_.
+ bool check_linkage_conditions_;
+ // See CompilerOptions.crash_on_linkage_violation_.
+ bool crash_on_linkage_violation_;
// Directory of relative classpaths.
std::string classpath_dir_;
diff --git a/dex2oat/dex2oat_options.cc b/dex2oat/dex2oat_options.cc
index 58944ff..ea72d54 100644
--- a/dex2oat/dex2oat_options.cc
+++ b/dex2oat/dex2oat_options.cc
@@ -224,6 +224,10 @@
.IntoKey(M::VeryLargeAppThreshold)
.Define("--force-determinism")
.IntoKey(M::ForceDeterminism)
+ .Define("--check-linkage-conditions")
+ .IntoKey(M::CheckLinkageConditions)
+ .Define("--crash-on-linkage-violation")
+ .IntoKey(M::CrashOnLinkageViolation)
.Define("--copy-dex-files=_")
.WithType<linker::CopyOption>()
.WithValueMap({{"true", linker::CopyOption::kOnlyIfCompressed},
diff --git a/dex2oat/dex2oat_options.def b/dex2oat/dex2oat_options.def
index f48806c..e324e8b 100644
--- a/dex2oat/dex2oat_options.def
+++ b/dex2oat/dex2oat_options.def
@@ -91,5 +91,7 @@
DEX2OAT_OPTIONS_KEY (std::string, DirtyImageObjects)
DEX2OAT_OPTIONS_KEY (std::vector<std::string>, RuntimeOptions)
DEX2OAT_OPTIONS_KEY (std::string, CompilationReason)
+DEX2OAT_OPTIONS_KEY (Unit, CheckLinkageConditions)
+DEX2OAT_OPTIONS_KEY (Unit, CrashOnLinkageViolation)
#undef DEX2OAT_OPTIONS_KEY
diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc
index 687e3ff..7ba5484 100644
--- a/dex2oat/dex2oat_test.cc
+++ b/dex2oat/dex2oat_test.cc
@@ -2422,4 +2422,28 @@
RunTest();
}
+class LinkageTest : public Dex2oatTest {};
+
+TEST_F(LinkageTest, LinkageEnabled) {
+ std::unique_ptr<const DexFile> dex(OpenTestDexFile("LinkageTest"));
+ std::string out_dir = GetScratchDir();
+ const std::string base_oat_name = out_dir + "/base.oat";
+ std::string error_msg;
+ const int res_fail = GenerateOdexForTestWithStatus(
+ {dex->GetLocation()},
+ base_oat_name,
+ CompilerFilter::Filter::kQuicken,
+ &error_msg,
+ {"--check-linkage-conditions", "--crash-on-linkage-violation"});
+ EXPECT_NE(0, res_fail);
+
+ const int res_no_fail = GenerateOdexForTestWithStatus(
+ {dex->GetLocation()},
+ base_oat_name,
+ CompilerFilter::Filter::kQuicken,
+ &error_msg,
+ {"--check-linkage-conditions"});
+ EXPECT_EQ(0, res_no_fail);
+}
+
} // namespace art
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index 15c7c65..b97f1db 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -1596,7 +1596,7 @@
// generated code.
const dex::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
ScopedObjectAccess soa(self);
- StackHandleScope<2> hs(soa.Self());
+ StackHandleScope<5> hs(soa.Self());
Handle<mirror::ClassLoader> class_loader(
hs.NewHandle(soa.Decode<mirror::ClassLoader>(jclass_loader)));
Handle<mirror::DexCache> dex_cache(hs.NewHandle(class_linker->FindDexCache(
@@ -1611,6 +1611,40 @@
CheckAndClearResolveException(soa.Self());
resolve_fields_and_methods = false;
} else {
+ Handle<mirror::Class> hklass(hs.NewHandle(klass));
+ if (manager_->GetCompiler()->GetCompilerOptions().IsCheckLinkageConditions() &&
+ !manager_->GetCompiler()->GetCompilerOptions().IsBootImage()) {
+ bool is_fatal = manager_->GetCompiler()->GetCompilerOptions().IsCrashOnLinkageViolation();
+ ObjPtr<mirror::ClassLoader> resolving_class_loader = hklass->GetClassLoader();
+ if (resolving_class_loader != soa.Decode<mirror::ClassLoader>(jclass_loader)) {
+ // Redefinition via different ClassLoaders.
+ // This OptStat stuff is to enable logging from the APK scanner.
+ if (is_fatal)
+ LOG(FATAL) << "OptStat#" << hklass->PrettyClassAndClassLoader() << ": 1";
+ else
+ LOG(ERROR)
+ << "LINKAGE VIOLATION: "
+ << hklass->PrettyClassAndClassLoader()
+ << " was redefined";
+ }
+ // Check that the current class is not a subclass of java.lang.ClassLoader.
+ if (!hklass->IsInterface() &&
+ hklass->IsSubClass(class_linker->FindClass(self,
+ "Ljava/lang/ClassLoader;",
+ hs.NewHandle(resolving_class_loader)))) {
+ // Subclassing of java.lang.ClassLoader.
+ // This OptStat stuff is to enable logging from the APK scanner.
+ if (is_fatal)
+ LOG(FATAL) << "OptStat#" << hklass->PrettyClassAndClassLoader() << ": 1";
+ else
+ LOG(ERROR)
+ << "LINKAGE VIOLATION: "
+ << hklass->PrettyClassAndClassLoader()
+ << " is a subclass of java.lang.ClassLoader";
+ }
+ CHECK(hklass->IsResolved()) << hklass->PrettyClass();
+ klass.Assign(hklass.Get());
+ }
// We successfully resolved a class, should we skip it?
if (SkipClass(jclass_loader, dex_file, klass)) {
return;
diff --git a/test/LinkageTest/Main.smali b/test/LinkageTest/Main.smali
new file mode 100644
index 0000000..267dacf
--- /dev/null
+++ b/test/LinkageTest/Main.smali
@@ -0,0 +1,21 @@
+# Copyright (C) 2020 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.
+
+.class public LMain;
+.super Ljava/lang/Object;
+
+.method public static main([Ljava/lang/String;)V
+ .registers 1
+ return-void
+.end method
diff --git a/test/LinkageTest/MyClassLoader.smali b/test/LinkageTest/MyClassLoader.smali
new file mode 100644
index 0000000..e06e9a0
--- /dev/null
+++ b/test/LinkageTest/MyClassLoader.smali
@@ -0,0 +1,22 @@
+# Copyright (C) 2020 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.
+
+.class public LMyClassLoader;
+.super Ldalvik/system/PathClassLoader;
+
+.method public static getNull()Ljava/lang/Object;
+ .registers 1
+ const v0, 0x0
+ return-object v0
+.end method
diff --git a/test/LinkageTest/Object.smali b/test/LinkageTest/Object.smali
new file mode 100644
index 0000000..35c6c77
--- /dev/null
+++ b/test/LinkageTest/Object.smali
@@ -0,0 +1,21 @@
+# Copyright (C) 2020 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.
+
+.class public Ljava/lang/Object;
+
+.method public static $noinline$bar()LUnresolved;
+ .registers 1
+ const v0, 0x0
+ return-object v0
+.end method