diff options
-rw-r--r-- | build/Android.common_test.mk | 1 | ||||
-rw-r--r-- | build/Android.oat.mk | 26 | ||||
-rw-r--r-- | cmdline/cmdline_parser_test.cc | 11 | ||||
-rw-r--r-- | oatdump/oatdump.cc | 7 | ||||
-rw-r--r-- | runtime/class_linker.cc | 12 | ||||
-rw-r--r-- | runtime/parsed_options.cc | 11 | ||||
-rw-r--r-- | runtime/runtime.cc | 10 | ||||
-rw-r--r-- | runtime/runtime.h | 10 | ||||
-rw-r--r-- | runtime/runtime_options.def | 3 | ||||
-rw-r--r-- | runtime/runtime_options.h | 1 | ||||
-rw-r--r-- | runtime/verifier/verify_mode.h | 35 | ||||
-rw-r--r-- | test/Android.run-test.mk | 31 | ||||
-rwxr-xr-x | test/etc/run-test-jar | 16 | ||||
-rwxr-xr-x | test/run-test | 7 |
14 files changed, 153 insertions, 28 deletions
diff --git a/build/Android.common_test.mk b/build/Android.common_test.mk index 45b649047f..2f43f5f809 100644 --- a/build/Android.common_test.mk +++ b/build/Android.common_test.mk @@ -45,6 +45,7 @@ ART_TEST_DEFAULT_COMPILER ?= true # Do you want interpreter tests run? ART_TEST_INTERPRETER ?= $(ART_TEST_FULL) +ART_TEST_INTERPRETER_ACCESS_CHECKS ?= $(ART_TEST_FULL) # Do you want JIT tests run? ART_TEST_JIT ?= $(ART_TEST_FULL) diff --git a/build/Android.oat.mk b/build/Android.oat.mk index 728469c2c4..c70e12deec 100644 --- a/build/Android.oat.mk +++ b/build/Android.oat.mk @@ -31,7 +31,7 @@ ifeq ($($(HOST_2ND_ARCH_VAR_PREFIX)DEX2OAT_HOST_INSTRUCTION_SET_FEATURES),) endif # Use dex2oat debug version for better error reporting -# $(1): compiler - default, optimizing, jit or interpreter. +# $(1): compiler - default, optimizing, jit, interpreter or interpreter-access-checks. # $(2): pic/no-pic # $(3): 2ND_ or undefined, 2ND_ for 32-bit host builds. # $(4): wrapper, e.g., valgrind. @@ -64,12 +64,16 @@ define create-core-oat-host-rules core_compile_options += --compiler-filter=interpret-only core_infix := -interpreter endif + ifeq ($(1),interpreter-access-checks) + core_compile_options += --compiler-filter=verify-at-runtime --runtime-arg -Xverify:softfail + core_infix := -interpreter-access-checks + endif ifeq ($(1),default) # Default has no infix, no compile options. endif - ifneq ($(filter-out default interpreter jit optimizing,$(1)),) + ifneq ($(filter-out default interpreter interpreter-access-checks jit optimizing,$(1)),) #Technically this test is not precise, but hopefully good enough. - $$(error found $(1) expected default, interpreter, jit or optimizing) + $$(error found $(1) expected default, interpreter, interpreter-access-checks, jit or optimizing) endif ifeq ($(2),pic) @@ -127,7 +131,7 @@ $$(core_oat_name): $$(core_image_name) core_pic_infix := endef # create-core-oat-host-rules -# $(1): compiler - default, optimizing, jit or interpreter. +# $(1): compiler - default, optimizing, jit, interpreter or interpreter-access-checks. # $(2): wrapper. # $(3): dex2oat suffix. define create-core-oat-host-rule-combination @@ -143,12 +147,14 @@ endef $(eval $(call create-core-oat-host-rule-combination,default,,)) $(eval $(call create-core-oat-host-rule-combination,optimizing,,)) $(eval $(call create-core-oat-host-rule-combination,interpreter,,)) +$(eval $(call create-core-oat-host-rule-combination,interpreter-access-checks,,)) valgrindHOST_CORE_IMG_OUTS := valgrindHOST_CORE_OAT_OUTS := $(eval $(call create-core-oat-host-rule-combination,default,valgrind,32)) $(eval $(call create-core-oat-host-rule-combination,optimizing,valgrind,32)) $(eval $(call create-core-oat-host-rule-combination,interpreter,valgrind,32)) +$(eval $(call create-core-oat-host-rule-combination,interpreter-access-checks,valgrind,32)) valgrind-test-art-host-dex2oat-host: $(valgrindHOST_CORE_IMG_OUTS) @@ -178,12 +184,16 @@ define create-core-oat-target-rules core_compile_options += --compiler-filter=interpret-only core_infix := -interpreter endif + ifeq ($(1),interpreter-access-checks) + core_compile_options += --compiler-filter=verify-at-runtime --runtime-arg -Xverify:softfail + core_infix := -interpreter-access-checks + endif ifeq ($(1),default) # Default has no infix, no compile options. endif - ifneq ($(filter-out default interpreter jit optimizing,$(1)),) + ifneq ($(filter-out default interpreter interpreter-access-checks jit optimizing,$(1)),) # Technically this test is not precise, but hopefully good enough. - $$(error found $(1) expected default, interpreter, jit or optimizing) + $$(error found $(1) expected default, interpreter, interpreter-access-checks, jit or optimizing) endif ifeq ($(2),pic) @@ -246,7 +256,7 @@ $$(core_oat_name): $$(core_image_name) core_pic_infix := endef # create-core-oat-target-rules -# $(1): compiler - default, optimizing, jit or interpreter. +# $(1): compiler - default, optimizing, jit, interpreter or interpreter-access-checks. # $(2): wrapper. # $(3): dex2oat suffix. define create-core-oat-target-rule-combination @@ -262,12 +272,14 @@ endef $(eval $(call create-core-oat-target-rule-combination,default,,)) $(eval $(call create-core-oat-target-rule-combination,optimizing,,)) $(eval $(call create-core-oat-target-rule-combination,interpreter,,)) +$(eval $(call create-core-oat-target-rule-combination,interpreter-access-checks,,)) valgrindTARGET_CORE_IMG_OUTS := valgrindTARGET_CORE_OAT_OUTS := $(eval $(call create-core-oat-target-rule-combination,default,valgrind,32)) $(eval $(call create-core-oat-target-rule-combination,optimizing,valgrind,32)) $(eval $(call create-core-oat-target-rule-combination,interpreter,valgrind,32)) +$(eval $(call create-core-oat-target-rule-combination,interpreter-access-checks,valgrind,32)) valgrind-test-art-host-dex2oat-target: $(valgrindTARGET_CORE_IMG_OUTS) diff --git a/cmdline/cmdline_parser_test.cc b/cmdline/cmdline_parser_test.cc index 98fd327f02..52df7deb25 100644 --- a/cmdline/cmdline_parser_test.cc +++ b/cmdline/cmdline_parser_test.cc @@ -216,9 +216,6 @@ TEST_F(CmdlineParserTest, TestSimpleSuccesses) { EXPECT_SINGLE_PARSE_EXISTS("-Xzygote", M::Zygote); EXPECT_SINGLE_PARSE_VALUE_STR("/hello/world", "-Xbootclasspath:/hello/world", M::BootClassPath); EXPECT_SINGLE_PARSE_VALUE("/hello/world", "-Xbootclasspath:/hello/world", M::BootClassPath); - EXPECT_SINGLE_PARSE_VALUE(false, "-Xverify:none", M::Verify); - EXPECT_SINGLE_PARSE_VALUE(true, "-Xverify:remote", M::Verify); - EXPECT_SINGLE_PARSE_VALUE(true, "-Xverify:all", M::Verify); EXPECT_SINGLE_PARSE_VALUE(Memory<1>(234), "-Xss234", M::StackSize); EXPECT_SINGLE_PARSE_VALUE(MemoryKiB(1234*MB), "-Xms1234m", M::MemoryInitialSize); EXPECT_SINGLE_PARSE_VALUE(true, "-XX:EnableHSpaceCompactForOOM", M::EnableHSpaceCompactForOOM); @@ -550,6 +547,14 @@ TEST_F(CmdlineParserTest, TestExperimentalLambdas) { M::ExperimentalLambdas); } +// -Xverify:_ +TEST_F(CmdlineParserTest, TestVerify) { + EXPECT_SINGLE_PARSE_VALUE(verifier::VerifyMode::kNone, "-Xverify:none", M::Verify); + EXPECT_SINGLE_PARSE_VALUE(verifier::VerifyMode::kEnable, "-Xverify:remote", M::Verify); + EXPECT_SINGLE_PARSE_VALUE(verifier::VerifyMode::kEnable, "-Xverify:all", M::Verify); + EXPECT_SINGLE_PARSE_VALUE(verifier::VerifyMode::kSoftFail, "-Xverify:softfail", M::Verify); +} + TEST_F(CmdlineParserTest, TestIgnoreUnrecognized) { RuntimeParser::Builder parserBuilder; diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc index e0d77086a7..93254547d7 100644 --- a/oatdump/oatdump.cc +++ b/oatdump/oatdump.cc @@ -1950,9 +1950,12 @@ class ImageDumper { } state->stats_.managed_code_bytes_ignoring_deduplication += quick_oat_code_size; + uint32_t method_access_flags = method->GetAccessFlags(); + indent_os << StringPrintf("OAT CODE: %p-%p\n", quick_oat_code_begin, quick_oat_code_end); - indent_os << StringPrintf("SIZE: Dex Instructions=%zd GC=%zd Mapping=%zd\n", - dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes); + indent_os << StringPrintf("SIZE: Dex Instructions=%zd GC=%zd Mapping=%zd AccessFlags=0x%x\n", + dex_instruction_bytes, gc_map_bytes, pc_mapping_table_bytes, + method_access_flags); size_t total_size = dex_instruction_bytes + gc_map_bytes + pc_mapping_table_bytes + vmap_table_bytes + quick_oat_code_size + ArtMethod::ObjectSize(image_pointer_size); diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 5798c04ba8..8f7862a3b9 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -3040,6 +3040,18 @@ void ClassLinker::VerifyClass(Thread* self, Handle<mirror::Class> klass) { mirror::Class::SetStatus(klass, mirror::Class::kStatusVerifyingAtRuntime, self); } + // Skip verification if we are forcing a soft fail. + // This has to be before the normal verification enabled check, + // since technically verification is disabled in this mode. + if (UNLIKELY(Runtime::Current()->IsVerificationSoftFail())) { + // Force verification to be a 'soft failure'. + mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self); + // As this is a fake verified status, make sure the methods are _not_ marked preverified + // later. + klass->SetPreverified(); + return; + } + // Skip verification if disabled. if (!Runtime::Current()->IsVerificationEnabled()) { mirror::Class::SetStatus(klass, mirror::Class::kStatusVerified, self); diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index d08af71e6e..77723545a2 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -244,10 +244,11 @@ std::unique_ptr<RuntimeParser> ParsedOptions::MakeParser(bool ignore_unrecognize .AppendValues() .IntoKey(M::ImageCompilerOptions) .Define("-Xverify:_") - .WithType<bool>() - .WithValueMap({{"none", false}, - {"remote", true}, - {"all", true}}) + .WithType<verifier::VerifyMode>() + .WithValueMap({{"none", verifier::VerifyMode::kNone}, + {"remote", verifier::VerifyMode::kEnable}, + {"all", verifier::VerifyMode::kEnable}, + {"softfail", verifier::VerifyMode::kSoftFail}}) .IntoKey(M::Verify) .Define("-XX:NativeBridge=_") .WithType<std::string>() @@ -686,7 +687,7 @@ void ParsedOptions::Usage(const char* fmt, ...) { UsageMessage(stream, " -esa\n"); UsageMessage(stream, " -dsa\n"); UsageMessage(stream, " (-enablesystemassertions, -disablesystemassertions)\n"); - UsageMessage(stream, " -Xverify:{none,remote,all}\n"); + UsageMessage(stream, " -Xverify:{none,remote,all,softfail}\n"); UsageMessage(stream, " -Xrs\n"); UsageMessage(stream, " -Xint:portable, -Xint:fast, -Xint:jit\n"); UsageMessage(stream, " -Xdexopt:{none,verified,all,full}\n"); diff --git a/runtime/runtime.cc b/runtime/runtime.cc index 3b0ca9e28a..c5aece56be 100644 --- a/runtime/runtime.cc +++ b/runtime/runtime.cc @@ -185,7 +185,7 @@ Runtime::Runtime() system_class_loader_(nullptr), dump_gc_performance_on_shutdown_(false), preinitialization_transaction_(nullptr), - verify_(false), + verify_(verifier::VerifyMode::kNone), allow_dex_file_fallback_(true), target_sdk_version_(0), implicit_null_checks_(false), @@ -1757,4 +1757,12 @@ void Runtime::SetImtUnimplementedMethod(ArtMethod* method) { imt_unimplemented_method_ = method; } +bool Runtime::IsVerificationEnabled() const { + return verify_ == verifier::VerifyMode::kEnable; +} + +bool Runtime::IsVerificationSoftFail() const { + return verify_ == verifier::VerifyMode::kSoftFail; +} + } // namespace art diff --git a/runtime/runtime.h b/runtime/runtime.h index 9ee96a3d1b..806292f3d6 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -64,6 +64,7 @@ namespace mirror { } // namespace mirror namespace verifier { class MethodVerifier; + enum class VerifyMode : int8_t; } // namespace verifier class ArenaPool; class ArtMethod; @@ -500,9 +501,8 @@ class Runtime { return !implicit_so_checks_; } - bool IsVerificationEnabled() const { - return verify_; - } + bool IsVerificationEnabled() const; + bool IsVerificationSoftFail() const; bool IsDexFileFallbackEnabled() const { return allow_dex_file_fallback_; @@ -700,8 +700,8 @@ class Runtime { // Transaction used for pre-initializing classes at compilation time. Transaction* preinitialization_transaction_; - // If false, verification is disabled. True by default. - bool verify_; + // If kNone, verification is disabled. kEnable by default. + verifier::VerifyMode verify_; // If true, the runtime may use dex files directly with the interpreter if an oat file is not // available/usable. diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def index dc4c0c7493..9922c5f993 100644 --- a/runtime/runtime_options.def +++ b/runtime/runtime_options.def @@ -106,7 +106,8 @@ RUNTIME_OPTIONS_KEY (std::vector<std::string>, \ CompilerOptions) // -Xcompiler-option ... RUNTIME_OPTIONS_KEY (std::vector<std::string>, \ ImageCompilerOptions) // -Ximage-compiler-option ... -RUNTIME_OPTIONS_KEY (bool, Verify, true) +RUNTIME_OPTIONS_KEY (verifier::VerifyMode, \ + Verify, verifier::VerifyMode::kEnable) RUNTIME_OPTIONS_KEY (std::string, NativeBridge) RUNTIME_OPTIONS_KEY (unsigned int, ZygoteMaxFailedBoots, 10) RUNTIME_OPTIONS_KEY (Unit, NoDexFileFallback) diff --git a/runtime/runtime_options.h b/runtime/runtime_options.h index 7e59000e09..88ac00a672 100644 --- a/runtime/runtime_options.h +++ b/runtime/runtime_options.h @@ -32,6 +32,7 @@ #include "gc/space/large_object_space.h" #include "profiler_options.h" #include "arch/instruction_set.h" +#include "verifier/verify_mode.h" #include <stdio.h> #include <stdarg.h> diff --git a/runtime/verifier/verify_mode.h b/runtime/verifier/verify_mode.h new file mode 100644 index 0000000000..bea43787c1 --- /dev/null +++ b/runtime/verifier/verify_mode.h @@ -0,0 +1,35 @@ +/* + * 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_ diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk index 65ddf8da17..3d5c483a3b 100644 --- a/test/Android.run-test.mk +++ b/test/Android.run-test.mk @@ -112,6 +112,9 @@ COMPILER_TYPES := ifeq ($(ART_TEST_DEFAULT_COMPILER),true) COMPILER_TYPES += default endif +ifeq ($(ART_TEST_INTERPRETER_ACCESS_CHECKS),true) + COMPILER_TYPES += interpreter-access-checks +endif ifeq ($(ART_TEST_INTERPRETER),true) COMPILER_TYPES += interpreter endif @@ -260,6 +263,28 @@ endif TEST_ART_BROKEN_NO_RELOCATE_TESTS := +# Temporarily disable some broken tests when forcing access checks in interpreter b/22414682 +TEST_ART_BROKEN_INTERPRETER_ACCESS_CHECK_TESTS := \ + 004-JniTest \ + 005-annotations \ + 044-proxy \ + 073-mismatched-field \ + 088-monitor-verification \ + 135-MirandaDispatch \ + 137-cfi \ + 412-new-array \ + 471-uninitialized-locals \ + 506-verify-aput \ + 800-smali + +ifneq (,$(filter interpreter-access-checks,$(COMPILER_TYPES))) + ART_TEST_KNOWN_BROKEN += $(call all-run-test-names,$(TARGET_TYPES),$(RUN_TYPES),$(PREBUILD_TYPES), \ + interpreter-access-checks,$(RELOCATE_TYPES),$(TRACE_TYPES),$(GC_TYPES),$(JNI_TYPES), \ + $(IMAGE_TYPES), $(PICTEST_TYPES), $(DEBUGGABLE_TYPES), $(TEST_ART_BROKEN_INTERPRETER_ACCESS_CHECK_TESTS), $(ALL_ADDRESS_SIZES)) +endif + +TEST_ART_BROKEN_INTERPRETER_ACCESS_CHECK_TESTS := + # Tests that are broken with GC stress. # 137-cfi needs to unwind a second forked process. We're using a primitive sleep to wait till we # hope the second process got into the expected state. The slowness of gcstress makes this bad. @@ -604,7 +629,8 @@ endif # Create a rule to build and run a tests following the form: # test-art-{1: host or target}-run-test-{2: debug ndebug}-{3: prebuild no-prebuild no-dex2oat}- -# {4: interpreter default optimizing jit}-{5: relocate nrelocate relocate-npatchoat}- +# {4: interpreter default optimizing jit interpreter-access-checks}- +# {5: relocate nrelocate relocate-npatchoat}- # {6: trace or ntrace}-{7: gcstress gcverify cms}-{8: forcecopy checkjni jni}- # {9: no-image image picimage}-{10: pictest npictest}- # {11: ndebuggable debuggable}-{12: test name}{13: 32 or 64} @@ -674,6 +700,9 @@ define define-test-art-run-test ifeq ($(4),interpreter) test_groups += ART_RUN_TEST_$$(uc_host_or_target)_INTERPRETER_RULES run_test_options += --interpreter + else ifeq ($(4),interpreter-access-checks) + test_groups += ART_RUN_TEST_$$(uc_host_or_target)_INTERPRETER_ACCESS_CHECKS_RULES + run_test_options += --interpreter --verify-soft-fail else ifeq ($(4),default) test_groups += ART_RUN_TEST_$$(uc_host_or_target)_DEFAULT_RULES diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index 842d87e565..db64b77f6c 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -42,7 +42,7 @@ TIME_OUT="y" TIME_OUT_VALUE=10 USE_GDB="n" USE_JVM="n" -VERIFY="y" +VERIFY="y" # y=yes,n=no,s=softfail ZYGOTE="" DEX_VERIFY="" USE_DEX2OAT_AND_PATCHOAT="y" @@ -149,6 +149,9 @@ while true; do elif [ "x$1" = "x--no-verify" ]; then VERIFY="n" shift + elif [ "x$1" = "x--verify-soft-fail" ]; then + VERIFY="s" + shift elif [ "x$1" = "x--no-optimize" ]; then OPTIMIZE="n" shift @@ -201,7 +204,11 @@ if [ "$ZYGOTE" = "" ]; then if [ "$VERIFY" = "y" ]; then JVM_VERIFY_ARG="-Xverify:all" msg "Performing verification" - else + elif [ "$VERIFY" = "s" ]; then + JVM_VERIFY_ARG="Xverify:all" + DEX_VERIFY="-Xverify:softfail" + msg "Forcing verification to be soft fail" + else # VERIFY = "n" DEX_VERIFY="-Xverify:none" JVM_VERIFY_ARG="-Xverify:none" msg "Skipping verification" @@ -263,7 +270,10 @@ if [ "$INTERPRETER" = "y" ]; then INT_OPTS="-Xint" if [ "$VERIFY" = "y" ] ; then COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=interpret-only" - else + elif [ "$VERIFY" = "s" ]; then + COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-at-runtime" + DEX_VERIFY="${DEX_VERIFY} -Xverify:softfail" + else # VERIFY = "n" COMPILE_FLAGS="${COMPILE_FLAGS} --compiler-filter=verify-none" DEX_VERIFY="${DEX_VERIFY} -Xverify:none" fi diff --git a/test/run-test b/test/run-test index bdf680b98a..eabbab32a9 100755 --- a/test/run-test +++ b/test/run-test @@ -262,6 +262,10 @@ while true; do elif [ "x$1" = "x--no-verify" ]; then run_args="${run_args} --no-verify" shift + elif [ "x$1" = "x--verify-soft-fail" ]; then + run_args="${run_args} --verify-soft-fail" + image_suffix="-interpreter-access-checks" + shift elif [ "x$1" = "x--no-optimize" ]; then run_args="${run_args} --no-optimize" shift @@ -520,6 +524,9 @@ if [ "$usage" = "yes" ]; then echo " --optimizing Enable optimizing compiler (default)." echo " --quick Use Quick compiler (off by default)." echo " --no-verify Turn off verification (on by default)." + echo " --verify-soft-fail Force soft fail verification (off by default)." + echo " Verification is enabled if neither --no-verify" + echo " nor --verify-soft-fail is specified." echo " --no-optimize Turn off optimization (on by default)." echo " --no-precise Turn off precise GC (on by default)." echo " --zygote Spawn the process from the Zygote." \ |