diff options
Diffstat (limited to 'test')
19 files changed, 522 insertions, 137 deletions
diff --git a/test/1945-proxy-method-arguments/expected.txt b/test/1945-proxy-method-arguments/expected.txt new file mode 100644 index 0000000000..1824953202 --- /dev/null +++ b/test/1945-proxy-method-arguments/expected.txt @@ -0,0 +1,26 @@ +JNI_OnLoad called +proxy: $Proxy0 +Proxy for interface TestInterface.method0 + arg0: $Proxy0 +Proxy for interface TestInterface.method1 + arg0: $Proxy0 + arg1: java.lang.String "a" +Proxy for interface TestInterface.method10 + arg0: $Proxy0 + arg1: java.lang.String "one" + arg2: java.lang.String "two" + arg3: java.lang.String "three" + arg4: java.lang.String "four" + arg5: java.lang.String "five" + arg6: java.lang.String "six" + arg7: java.lang.String "seven" + arg8: java.lang.String "eight" + arg9: java.lang.String "nine" + arg10: java.lang.String "ten" +Proxy for interface TestInterface.method10Even + arg0: $Proxy0 + arg2: java.lang.String "two" + arg4: java.lang.String "four" + arg6: java.lang.String "six" + arg8: java.lang.String "eight" + arg10: java.lang.String "ten" diff --git a/test/1945-proxy-method-arguments/get_args.cc b/test/1945-proxy-method-arguments/get_args.cc new file mode 100644 index 0000000000..211ae10ab0 --- /dev/null +++ b/test/1945-proxy-method-arguments/get_args.cc @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2018 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. + */ + +#include "arch/context.h" +#include "art_method-inl.h" +#include "jni.h" +#include "oat_quick_method_header.h" +#include "scoped_thread_state_change-inl.h" +#include "stack.h" +#include "thread.h" + +namespace art { + +namespace { + +// Visit a proxy method Quick frame at a given depth. +class GetProxyQuickFrameVisitor FINAL : public StackVisitor { + public: + GetProxyQuickFrameVisitor(art::Thread* target, art::Context* ctx, size_t frame_depth) + REQUIRES_SHARED(art::Locks::mutator_lock_) + : art::StackVisitor(target, ctx, art::StackVisitor::StackWalkKind::kIncludeInlinedFrames), + cur_depth_(0u), + frame_depth_(frame_depth), + quick_frame_(nullptr) {} + + bool VisitFrame() OVERRIDE REQUIRES_SHARED(Locks::mutator_lock_) { + if (GetMethod()->IsRuntimeMethod()) { + return true; + } + if (cur_depth_ == frame_depth_) { + // Found frame. + ShadowFrame* shadow_frame = GetCurrentShadowFrame(); + if (shadow_frame != nullptr) { + // Nothing to do. + } else { + VisitQuickFrameAtSearchedDepth(); + } + return false; + } else { + ++cur_depth_; + return true; + } + } + + void VisitQuickFrameAtSearchedDepth() REQUIRES_SHARED(Locks::mutator_lock_) { + quick_frame_ = GetCurrentQuickFrame(); + CHECK(quick_frame_ != nullptr); + ArtMethod* method = *quick_frame_; + CHECK(method != nullptr); + CHECK(method->IsProxyMethod()) << method->PrettyMethod(); + } + + // Return the found Quick frame. + ArtMethod** GetQuickFrame() { + return quick_frame_; + } + + private: + // The depth of the currently visited frame. + size_t cur_depth_; + // The depth of the currently searched frame. + size_t frame_depth_; + // The quick frame, if found. + ArtMethod** quick_frame_; + // Method name + + DISALLOW_COPY_AND_ASSIGN(GetProxyQuickFrameVisitor); +}; + +extern "C" StackReference<mirror::Object>* artQuickGetProxyReferenceArgumentAt(size_t arg_pos, + ArtMethod** sp) + REQUIRES_SHARED(Locks::mutator_lock_); + +jobject GetProxyReferenceArgument(size_t arg_pos, size_t proxy_method_frame_depth) { + Thread* self = Thread::Current(); + ScopedObjectAccess soa(self); + std::unique_ptr<Context> context(Context::Create()); + + GetProxyQuickFrameVisitor visitor(self, context.get(), proxy_method_frame_depth); + visitor.WalkStack(); + ArtMethod** quick_frame = visitor.GetQuickFrame(); + CHECK(quick_frame != nullptr); + + // Find reference argument in frame. + StackReference<mirror::Object>* ref_arg = + artQuickGetProxyReferenceArgumentAt(arg_pos, quick_frame); + CHECK(ref_arg != nullptr); + art::ObjPtr<mirror::Object> obj = ref_arg->AsMirrorPtr(); + + return obj.IsNull() ? nullptr : soa.AddLocalReference<jobject>(obj); +} + +extern "C" JNIEXPORT jobject JNICALL Java_TestInvocationHandler_getArgument( + JNIEnv* env ATTRIBUTE_UNUSED, jobject thiz ATTRIBUTE_UNUSED, int arg_pos, int frame_depth) { + return GetProxyReferenceArgument(arg_pos, frame_depth); +} + +} // namespace + +} // namespace art diff --git a/test/1945-proxy-method-arguments/info.txt b/test/1945-proxy-method-arguments/info.txt new file mode 100644 index 0000000000..15ccc44ac9 --- /dev/null +++ b/test/1945-proxy-method-arguments/info.txt @@ -0,0 +1,7 @@ +Test checking that reference arguments of proxy methods are visited as +thread stack roots when visiting Quick frames roots (b/73149739). +Previously, if the proxy method (direcly or indirectly) executed code +accessing one of these reference arguments in the proxy method stack +frame, it could end up with a stale reference, as the corresponding +object may have been moved by the garbage collector, but the stack +reference would not have been updated. diff --git a/test/1945-proxy-method-arguments/src/Main.java b/test/1945-proxy-method-arguments/src/Main.java new file mode 100644 index 0000000000..b04a661a4b --- /dev/null +++ b/test/1945-proxy-method-arguments/src/Main.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2018 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. + */ + +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +interface TestInterface { + void method0(); + void method1(String arg); + void method10(String arg1, String arg2, String arg3, String arg4, String arg5, + String arg6, String arg7, String arg8, String arg9, String arg10); + void method10Even(byte arg1, String arg2, short arg3, String arg4, int arg5, + String arg6, long arg7, String arg8, double arg9, String arg10); +} + +class TestInvocationHandler implements InvocationHandler { + @Override + public Object invoke(Object proxy, Method method, Object[] args) { + // Force garbage collection to try to make `proxy` move in memory + // (in the case of a moving garbage collector). + System.gc(); + + System.out.println("Proxy for " + TestInterface.class + "." + method.getName()); + if (method.getName().equals("method0")) { + testMethod0(proxy, args); + } else if (method.getName().equals("method1")) { + testMethod1(proxy, args); + } else if (method.getName().equals("method10")) { + testMethod10(proxy, args); + } else if (method.getName().equals("method10Even")) { + testMethod10Even(proxy, args); + } + return null; + } + + private void testMethod0(Object proxy, Object[] args) { + // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation). + Object arg0 = getProxyMethodArgument(0); + System.out.println(" arg0: " + arg0.getClass().getName()); + Main.assertEquals(proxy, arg0); + } + + private void testMethod1(Object proxy, Object[] args) { + // Get argument 0 (method target) from the proxy method frame ($Proxy0.method0 activation). + Object arg0 = getProxyMethodArgument(0); + System.out.println(" arg0: " + arg0.getClass().getName()); + Main.assertEquals(proxy, arg0); + // Get argument 1 from the proxy method frame ($Proxy0.method1 activation). + String arg1 = (String) getProxyMethodArgument(1); + System.out.println(" arg1: " + arg1.getClass().getName() + " \"" + arg1 + "\""); + Main.assertEquals(args[0], arg1); + } + + private void testMethod10(Object proxy, Object[] args) { + // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10 activation). + Object arg0 = getProxyMethodArgument(0); + System.out.println(" arg0: " + arg0.getClass().getName()); + Main.assertEquals(proxy, arg0); + // Get argument `i` from the proxy method frame ($Proxy0.method10 activation). + for (int i = 0; i < 10; ++i) { + int arg_pos = i + 1; + String arg = (String) getProxyMethodArgument(arg_pos); + System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\""); + Main.assertEquals(args[i], arg); + } + } + + private void testMethod10Even(Object proxy, Object[] args) { + // Get argument 0 (method target) from the proxy method frame ($Proxy0.method10Even + // activation). + Object arg0 = getProxyMethodArgument(0); + System.out.println(" arg0: " + arg0.getClass().getName()); + Main.assertEquals(proxy, arg0); + // Get argument `i` from the proxy method frame ($Proxy0.method10Even activation). + for (int i = 1; i < 10; i += 2) { + int arg_pos = i + 1; + String arg = (String) getProxyMethodArgument(arg_pos); + System.out.println(" arg" + arg_pos + ": " + arg.getClass().getName() + " \"" + arg + "\""); + Main.assertEquals(args[i], arg); + } + } + + // Get reference argument at position `arg_pos` in proxy frame. + // This method should only be called from one of the + // `TestInvocationHandler.testMethod*` methods via `TestInvocationHandler.invoke`. + private Object getProxyMethodArgument(int arg_pos) { + // Find proxy frame in stack (from a testMethod* method). + // + // depth method + // ---------------------------------------------------------------------- + // 0 TestInvocationHandler.getArgument (outermost frame) + // 1 TestInvocationHandler.getProxyMethodArgument + // 2 TestInvocationHandler.testMethod* + // 3 TestInvocationHandler.invoke + // 4 java.lang.reflect.Proxy.invoke + // -> 5 TestInterface.method* (proxy method) + // 6 Main.main (innermost frame) + // + int proxy_method_frame_depth = 5; + return getArgument(arg_pos, proxy_method_frame_depth); + } + + // Get reference argument at position `arg_pos` in frame at depth `frame_depth`. + private native Object getArgument(int arg_pos, int frame_depth); +} + +public class Main { + public static void main(String[] args) { + System.loadLibrary(args[0]); + + TestInvocationHandler invocationHandler = new TestInvocationHandler(); + TestInterface proxy = (TestInterface) Proxy.newProxyInstance( + Main.class.getClassLoader(), + new Class<?>[] { TestInterface.class }, + invocationHandler); + System.out.println("proxy: " + proxy.getClass().getName()); + + proxy.method0(); + proxy.method1("a"); + proxy.method10("one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); + proxy.method10Even((byte) 1, "two", (short) 3, "four", 5, "six", 7L, "eight", 9.0, "ten"); + } + + public static void assertEquals(Object expected, Object actual) { + if (expected != actual) { + throw new Error("Expected " + expected + ", got " + actual); + } + } + + public static void assertEquals(String expected, String actual) { + if (expected != actual) { + throw new Error("Expected \"" + expected + "\", got \"" + actual + "\""); + } + } +} diff --git a/test/990-method-handle-and-mr/build b/test/807-method-handle-and-mr/build index 12a8e18d0b..12a8e18d0b 100755 --- a/test/990-method-handle-and-mr/build +++ b/test/807-method-handle-and-mr/build diff --git a/test/990-method-handle-and-mr/expected.txt b/test/807-method-handle-and-mr/expected.txt index 8483fb5045..8483fb5045 100644 --- a/test/990-method-handle-and-mr/expected.txt +++ b/test/807-method-handle-and-mr/expected.txt diff --git a/test/990-method-handle-and-mr/info.txt b/test/807-method-handle-and-mr/info.txt index 85a957ceea..85a957ceea 100644 --- a/test/990-method-handle-and-mr/info.txt +++ b/test/807-method-handle-and-mr/info.txt diff --git a/test/990-method-handle-and-mr/src/Main.java b/test/807-method-handle-and-mr/src/Main.java index 739b8eb551..739b8eb551 100644 --- a/test/990-method-handle-and-mr/src/Main.java +++ b/test/807-method-handle-and-mr/src/Main.java diff --git a/test/912-classes/src-art/art/Test912.java b/test/912-classes/src-art/art/Test912.java index ddfadf3626..1a60185f49 100644 --- a/test/912-classes/src-art/art/Test912.java +++ b/test/912-classes/src-art/art/Test912.java @@ -398,6 +398,7 @@ public class Test912 { public static double dummy = Math.random(); // So it can't be compile-time initialized. } + @SuppressWarnings("RandomCast") private static class TestForInitFail { public static int dummy = ((int)Math.random())/0; // So it throws when initializing. } diff --git a/test/983-source-transform-verify/source_transform.cc b/test/983-source-transform-verify/source_transform.cc index dfefce207b..9e65a9964c 100644 --- a/test/983-source-transform-verify/source_transform.cc +++ b/test/983-source-transform-verify/source_transform.cc @@ -14,30 +14,13 @@ * limitations under the License. */ -#include <inttypes.h> +#include "source_transform.h" -#include <cstdio> -#include <cstring> -#include <iostream> -#include <vector> +#include "jni.h" #include "android-base/stringprintf.h" -#include "jni.h" #include "jvmti.h" - -#include "base/macros.h" -#include "bytecode_utils.h" -#include "dex/code_item_accessors-inl.h" -#include "dex/art_dex_file_loader.h" -#include "dex/dex_file.h" -#include "dex/dex_file_loader.h" -#include "dex/dex_instruction.h" -#include "jit/jit.h" -#include "native_stack_dump.h" -#include "runtime.h" -#include "scoped_thread_state_change-inl.h" -#include "thread-current-inl.h" -#include "thread_list.h" +#include "scoped_local_ref.h" // Test infrastructure #include "jvmti_helper.h" @@ -48,9 +31,18 @@ namespace Test983SourceTransformVerify { constexpr bool kSkipInitialLoad = true; +static void Println(JNIEnv* env, const char* msg) { + ScopedLocalRef<jclass> test_klass(env, env->FindClass("art/Test983")); + jmethodID println_method = env->GetStaticMethodID(test_klass.get(), + "doPrintln", + "(Ljava/lang/String;)V"); + ScopedLocalRef<jstring> data(env, env->NewStringUTF(msg)); + env->CallStaticVoidMethod(test_klass.get(), println_method, data.get()); +} + // The hook we are using. void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED, - JNIEnv* jni_env ATTRIBUTE_UNUSED, + JNIEnv* env, jclass class_being_redefined, jobject loader ATTRIBUTE_UNUSED, const char* name, @@ -60,78 +52,24 @@ void JNICALL CheckDexFileHook(jvmtiEnv* jvmti_env ATTRIBUTE_UNUSED, jint* new_class_data_len ATTRIBUTE_UNUSED, unsigned char** new_class_data ATTRIBUTE_UNUSED) { if (kSkipInitialLoad && class_being_redefined == nullptr) { - // Something got loaded concurrently. Just ignore it for now. + // Something got loaded concurrently. Just ignore it for now. To make sure the test is + // repeatable we only care about things that come from RetransformClasses. return; } - std::cout << "Dex file hook for " << name << std::endl; + Println(env, android::base::StringPrintf("Dex file hook for %s", name).c_str()); if (IsJVM()) { return; } - // Due to b/72402467 the class_data_len might just be an estimate. - CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header)); - const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data); - uint32_t header_file_size = header->file_size_; - CHECK_LE(static_cast<jint>(header_file_size), class_data_len); - class_data_len = static_cast<jint>(header_file_size); - - const ArtDexFileLoader dex_file_loader; - std::string error; - std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data, - class_data_len, - "fake_location.dex", - /*location_checksum*/ 0, - /*oat_dex_file*/ nullptr, - /*verify*/ true, - /*verify_checksum*/ true, - &error)); - if (dex.get() == nullptr) { - std::cout << "Failed to verify dex file for " << name << " because " << error << std::endl; - return; - } - for (uint32_t i = 0; i < dex->NumClassDefs(); i++) { - const DexFile::ClassDef& def = dex->GetClassDef(i); - const uint8_t* data_item = dex->GetClassData(def); - if (data_item == nullptr) { - continue; - } - for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) { - if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) { - continue; - } - for (const DexInstructionPcPair& pair : - art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) { - const Instruction& inst = pair.Inst(); - int forbiden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly); - if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER || - (inst.GetVerifyExtraFlags() & forbiden_flags) != 0) { - std::cout << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex()) - << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : " - << inst.DumpString(dex.get()) << std::endl; - continue; - } - } - } - } + VerifyClassData(class_data_len, class_data); } // Get all capabilities except those related to retransformation. -jint OnLoad(JavaVM* vm, - char* options ATTRIBUTE_UNUSED, - void* reserved ATTRIBUTE_UNUSED) { - if (vm->GetEnv(reinterpret_cast<void**>(&jvmti_env), JVMTI_VERSION_1_0)) { - printf("Unable to get jvmti env!\n"); - return 1; - } - SetStandardCapabilities(jvmti_env); +extern "C" JNIEXPORT void JNICALL Java_art_Test983_setupLoadHook(JNIEnv* env, jclass) { jvmtiEventCallbacks cb; memset(&cb, 0, sizeof(cb)); cb.ClassFileLoadHook = CheckDexFileHook; - if (jvmti_env->SetEventCallbacks(&cb, sizeof(cb)) != JVMTI_ERROR_NONE) { - printf("Unable to set class file load hook cb!\n"); - return 1; - } - return 0; + JvmtiErrorToException(env, jvmti_env, jvmti_env->SetEventCallbacks(&cb, sizeof(cb))); } } // namespace Test983SourceTransformVerify diff --git a/test/983-source-transform-verify/source_transform.h b/test/983-source-transform-verify/source_transform.h index db9415aec1..2206498cc3 100644 --- a/test/983-source-transform-verify/source_transform.h +++ b/test/983-source-transform-verify/source_transform.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2017 The Android Open Source Project + * 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. @@ -22,7 +22,7 @@ namespace art { namespace Test983SourceTransformVerify { -jint OnLoad(JavaVM* vm, char* options, void* reserved); +void VerifyClassData(jint class_data_len, const unsigned char* class_data); } // namespace Test983SourceTransformVerify } // namespace art diff --git a/test/983-source-transform-verify/source_transform_art.cc b/test/983-source-transform-verify/source_transform_art.cc new file mode 100644 index 0000000000..5353370ac6 --- /dev/null +++ b/test/983-source-transform-verify/source_transform_art.cc @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2017 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. + */ + +#include "source_transform.h" + +#include <inttypes.h> + +#include <memory> + +#include <android-base/logging.h> + +#include "dex/code_item_accessors-inl.h" +#include "dex/art_dex_file_loader.h" +#include "dex/dex_file.h" +#include "dex/dex_file_loader.h" +#include "dex/dex_instruction.h" + +namespace art { +namespace Test983SourceTransformVerify { + +// The hook we are using. +void VerifyClassData(jint class_data_len, const unsigned char* class_data) { + // Due to b/72402467 the class_data_len might just be an estimate. + CHECK_GE(static_cast<size_t>(class_data_len), sizeof(DexFile::Header)); + const DexFile::Header* header = reinterpret_cast<const DexFile::Header*>(class_data); + uint32_t header_file_size = header->file_size_; + CHECK_LE(static_cast<jint>(header_file_size), class_data_len); + class_data_len = static_cast<jint>(header_file_size); + + const ArtDexFileLoader dex_file_loader; + std::string error; + std::unique_ptr<const DexFile> dex(dex_file_loader.Open(class_data, + class_data_len, + "fake_location.dex", + /*location_checksum*/ 0, + /*oat_dex_file*/ nullptr, + /*verify*/ true, + /*verify_checksum*/ true, + &error)); + CHECK(dex.get() != nullptr) << "Failed to verify dex: " << error; + for (uint32_t i = 0; i < dex->NumClassDefs(); i++) { + const DexFile::ClassDef& def = dex->GetClassDef(i); + const uint8_t* data_item = dex->GetClassData(def); + if (data_item == nullptr) { + continue; + } + for (ClassDataItemIterator it(*dex, data_item); it.HasNext(); it.Next()) { + if (!it.IsAtMethod() || it.GetMethodCodeItem() == nullptr) { + continue; + } + for (const DexInstructionPcPair& pair : + art::CodeItemInstructionAccessor(*dex, it.GetMethodCodeItem())) { + const Instruction& inst = pair.Inst(); + int forbidden_flags = (Instruction::kVerifyError | Instruction::kVerifyRuntimeOnly); + if (inst.Opcode() == Instruction::RETURN_VOID_NO_BARRIER || + (inst.GetVerifyExtraFlags() & forbidden_flags) != 0) { + LOG(FATAL) << "Unexpected instruction found in " << dex->PrettyMethod(it.GetMemberIndex()) + << " [Dex PC: 0x" << std::hex << pair.DexPc() << std::dec << "] : " + << inst.DumpString(dex.get()) << std::endl; + } + } + } + } +} + +} // namespace Test983SourceTransformVerify +} // namespace art diff --git a/test/983-source-transform-verify/source_transform_slicer.cc b/test/983-source-transform-verify/source_transform_slicer.cc new file mode 100644 index 0000000000..abf32e752e --- /dev/null +++ b/test/983-source-transform-verify/source_transform_slicer.cc @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2017 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. + */ + +#include "source_transform.h" + +#pragma clang diagnostic push +// slicer defines its own CHECK. b/65422458 +#pragma push_macro("CHECK") +#undef CHECK + +// Slicer's headers have code that triggers these warnings. b/65298177 +#pragma clang diagnostic ignored "-Wsign-compare" +#include "reader.h" + +#pragma pop_macro("CHECK") +#pragma clang diagnostic pop + +namespace art { +namespace Test983SourceTransformVerify { + +// The hook we are using. +void VerifyClassData(jint class_data_len, const unsigned char* class_data) { + dex::Reader reader(class_data, class_data_len); + reader.CreateFullIr(); // This will verify all bytecode. +} + +} // namespace Test983SourceTransformVerify +} // namespace art diff --git a/test/983-source-transform-verify/src/art/Test983.java b/test/983-source-transform-verify/src/art/Test983.java index faae96aef6..7dc47ab06a 100644 --- a/test/983-source-transform-verify/src/art/Test983.java +++ b/test/983-source-transform-verify/src/art/Test983.java @@ -27,7 +27,15 @@ public class Test983 { doTest(); } + private native static void setupLoadHook(); + + /* called from JNI */ + public static void doPrintln(String str) { + System.out.println(str); + } + public static void doTest() { + setupLoadHook(); Redefinition.enableCommonRetransformation(true); Redefinition.doCommonClassRetransformation(Transform.class); Redefinition.doCommonClassRetransformation(Object.class); diff --git a/test/Android.bp b/test/Android.bp index 5f39ffefa9..bf39ec4d9f 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -62,7 +62,7 @@ art_cc_defaults { "libvixld-arm", "libvixld-arm64", "libart-gtest", - "libdexfile", + "libdexfiled", "libbase", "libicuuc", @@ -114,7 +114,7 @@ art_cc_defaults { shared_libs: [ "libartd", "libartd-compiler", - "libdexfile", + "libdexfiled", ], static_libs: [ "libgtest", @@ -151,7 +151,7 @@ art_cc_library { shared_libs: [ "libartd", "libartd-compiler", - "libdexfile", + "libdexfiled", "libbase", "libbacktrace", ], @@ -169,7 +169,6 @@ cc_defaults { "art_defaults", ], shared_libs: [ - "libdexfile", "libbacktrace", "libbase", "libnativehelper", @@ -180,7 +179,10 @@ art_cc_test_library { name: "libartagent", srcs: ["900-hello-plugin/load_unload.cc"], defaults: ["libartagent-defaults"], - shared_libs: ["libart"], + shared_libs: [ + "libart", + "libdexfile", + ], } art_cc_test_library { @@ -190,7 +192,10 @@ art_cc_test_library { "art_debug_defaults", "libartagent-defaults", ], - shared_libs: ["libartd"], + shared_libs: [ + "libartd", + "libdexfiled", + ], } art_cc_defaults { @@ -238,6 +243,7 @@ art_cc_defaults { "931-agent-thread/agent_thread.cc", "933-misc-events/misc_events.cc", "945-obsolete-native/obsolete_native.cc", + "983-source-transform-verify/source_transform.cc", "984-obsolete-invoke/obsolete_invoke.cc", "986-native-method-bind/native_bind.cc", "987-agent-bind/agent_bind.cc", @@ -288,20 +294,22 @@ art_cc_defaults { "909-attach-agent/attach.cc", "912-classes/classes_art.cc", "936-search-onload/search_onload.cc", - "983-source-transform-verify/source_transform.cc", + "983-source-transform-verify/source_transform_art.cc", "1940-ddms-ext/ddm_ext.cc", "1944-sudden-exit/sudden_exit.cc", ], shared_libs: [ "libbase", - "libdexfile", ], } art_cc_test_library { name: "libtiagent", defaults: ["libtiagent-defaults"], - shared_libs: ["libart"], + shared_libs: [ + "libart", + "libdexfile", + ], } art_cc_test_library { @@ -310,24 +318,32 @@ art_cc_test_library { "art_debug_defaults", "libtiagent-defaults", ], - shared_libs: ["libartd"], + shared_libs: [ + "libartd", + "libdexfiled", + ], } -art_cc_test_library { +cc_library_static { name: "libctstiagent", defaults: ["libtiagent-base-defaults"], + host_supported: false, + srcs: [ + "983-source-transform-verify/source_transform_slicer.cc", + ], whole_static_libs: [ - "libdexfile", - "libz", - "libziparchive", + "slicer", + "libz", // for slicer (using adler32). ], static_libs: [ "libbase", - "libcutils", - "libutils", ], - shared_libs: [ - "liblog", + header_libs: [ + // This is needed to resolve the base/ header file in libdexfile. Unfortunately there are + // many problems with how we export headers that are making doing this the 'right' way + // difficult. + // TODO: move those headers to art/ rather than under runtime. + "libart_runtime_headers", ], export_include_dirs: ["ti-agent"], } @@ -367,11 +383,9 @@ cc_defaults { "art_defaults", ], srcs: [ - "common/runtime_state.cc", - "common/stack_inspect.cc", "004-JniTest/jni_test.cc", - "004-SignalTest/signaltest.cc", "004-ReferenceMap/stack_walk_refmap_jni.cc", + "004-SignalTest/signaltest.cc", "004-StackWalk/stack_walk_jni.cc", "004-ThreadStress/thread_stress.cc", "004-UnsafeTest/unsafe_test.cc", @@ -388,6 +402,7 @@ cc_defaults { "154-gc-loop/heap_interface.cc", "167-visit-locks/visit_locks.cc", "169-threadgroup-jni/jni_daemon_thread.cc", + "1945-proxy-method-arguments/get_args.cc", "203-multi-checkpoint/multi_checkpoint.cc", "305-other-fault-handler/fault_handler.cc", "454-get-vreg/get_vreg_jni.cc", @@ -411,9 +426,10 @@ cc_defaults { "667-jit-jni-stub/jit_jni_stub_test.cc", "674-hiddenapi/hiddenapi.cc", "708-jit-cache-churn/jit.cc", + "common/runtime_state.cc", + "common/stack_inspect.cc", ], shared_libs: [ - "libdexfile", "libbacktrace", "libbase", "libnativehelper", @@ -423,7 +439,10 @@ cc_defaults { art_cc_test_library { name: "libarttest", defaults: ["libarttest-defaults"], - shared_libs: ["libart"], + shared_libs: [ + "libart", + "libdexfile", + ], } art_cc_test_library { @@ -432,7 +451,10 @@ art_cc_test_library { "art_debug_defaults", "libarttest-defaults", ], - shared_libs: ["libartd"], + shared_libs: [ + "libartd", + "libdexfiled", + ], } art_cc_test_library { diff --git a/test/etc/run-test-jar b/test/etc/run-test-jar index bb6ace1b06..b8427f491b 100755 --- a/test/etc/run-test-jar +++ b/test/etc/run-test-jar @@ -850,7 +850,7 @@ if [ "$HOST" = "n" ]; then fi # System libraries needed by libarttestd.so - PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libbase.so:libnativehelper.so + PUBLIC_LIBS=libart.so:libartd.so:libc++.so:libbacktrace.so:libdexfile.so:libdexfiled.so:libbase.so:libnativehelper.so # Create a script with the command. The command can get longer than the longest # allowed adb command and there is no way to get the exit status from a adb shell diff --git a/test/knownfailures.json b/test/knownfailures.json index b483b93e19..ddf9098c64 100644 --- a/test/knownfailures.json +++ b/test/knownfailures.json @@ -377,12 +377,6 @@ "variant": "jvmti-stress & jit | redefine-stress & jit" }, { - "test_patterns": ["674-hiddenapi"], - "description": ["hiddenapi test is failing with redefine stress cdex"], - "bug": "http://b/72610009", - "variant": "redefine-stress & cdex-fast" - }, - { "test_patterns": ["616-cha"], "description": ["The test assumes a boot image exists."], "bug": "http://b/34193647", @@ -423,21 +417,13 @@ "variant": "redefine-stress & speed-profile | jvmti-stress & speed-profile" }, { - "tests": [ - "714-invoke-custom-lambda-metafactory", - "950-redefine-intrinsic", - "951-threaded-obsolete", - "952-invoke-custom", - "952-invoke-custom-kinds", - "953-invoke-polymorphic-compiler", - "954-invoke-polymorphic-verifier", - "955-methodhandles-smali", - "956-methodhandles", - "957-methodhandle-transforms", - "958-methodhandle-stackframe", - "959-invoke-polymorphic-accessors", - "979-const-method-handle", - "990-method-handle-and-mr" + "test_patterns": [ + ".*invoke-custom.*", + ".*invoke-polymorphic.*", + ".*methodhandle.*", + ".*method-handle.*", + ".*varhandle.*", + ".*var-handle.*" ], "description": [ "Tests that use invoke-polymorphic/invoke-custom which is not yet supported by", @@ -460,9 +446,22 @@ }, { "tests": [ + "132-daemon-locks-shutdown", + "607-daemon-stress", + "602-deoptimizeable", + "121-simple-suspend-check", + "083-compiler-regressions" + ], + "description": ["Tests that have failed on redefine stress for unknown reasons"], + "bug": "b/73177368", + "variant": "redefine-stress" + }, + { + "tests": [ "097-duplicate-method", "138-duplicate-classes-check2", "159-app-image-fields", + "674-hiddenapi", "649-vdex-duplicate-method", "804-class-extends-itself", "921-hello-failure" @@ -481,6 +480,7 @@ "626-const-class-linking", "629-vdex-speed", "647-jni-get-field-id", + "674-hiddenapi", "944-transform-classloaders" ], "description": [ @@ -494,7 +494,7 @@ "004-ThreadStress" ], "description": "The thread stress test just takes too long with field-stress", - "variant": "jvmti-stress | field-stress | step-stress" + "variant": "jvmti-stress | field-stress | step-stress | redefine-stress" }, { "tests": [ @@ -653,11 +653,6 @@ "description": ["Test is designed to only check --compiler-filter=speed"] }, { - "test_patterns": [".*"], - "description": ["Tests are timing out for weeks now, disable to fix."], - "variant": "cdex-fast & redefine-stress" - }, - { "tests": "674-HelloWorld-Dm", "variant": "target", "description": ["Requires zip, which isn't available on device"] diff --git a/test/testrunner/testrunner.py b/test/testrunner/testrunner.py index 3d173f5571..4329ad4863 100755 --- a/test/testrunner/testrunner.py +++ b/test/testrunner/testrunner.py @@ -110,6 +110,7 @@ test_count = 0 total_test_count = 0 verbose = False dry_run = False +ignore_skips = False build = False gdb = False gdb_arg = '' @@ -710,6 +711,8 @@ def is_test_disabled(test, variant_set): return True if test in env.EXTRA_DISABLED_TESTS: return True + if ignore_skips: + return False variants_list = DISABLED_TEST_CONTAINER.get(test, {}) for variants in variants_list: variants_present = True @@ -878,6 +881,7 @@ def get_default_threads(target): def parse_option(): global verbose global dry_run + global ignore_skips global n_thread global build global gdb @@ -897,6 +901,8 @@ def parse_option(): parser.add_argument('--dry-run', action='store_true', dest='dry_run') parser.add_argument("--skip", action="append", dest="skips", default=[], help="Skip the given test in all circumstances.") + parser.add_argument("--no-skips", dest="ignore_skips", action="store_true", default=False, + help="Don't skip any run-test configurations listed in knownfailures.json.") parser.add_argument('--no-build-dependencies', action='store_false', dest='build', help="Don't build dependencies under any circumstances. This is the " + @@ -935,6 +941,7 @@ def parse_option(): verbose = True if options['n_thread']: n_thread = max(1, options['n_thread']) + ignore_skips = options['ignore_skips'] if options['dry_run']: dry_run = True verbose = True diff --git a/test/ti-agent/common_load.cc b/test/ti-agent/common_load.cc index 9a7352e479..bfd165db10 100644 --- a/test/ti-agent/common_load.cc +++ b/test/ti-agent/common_load.cc @@ -28,7 +28,6 @@ #include "901-hello-ti-agent/basics.h" #include "909-attach-agent/attach.h" #include "936-search-onload/search_onload.h" -#include "983-source-transform-verify/source_transform.h" #include "1919-vminit-thread-start-timing/vminit.h" namespace art { @@ -83,7 +82,6 @@ static AgentLib agents[] = { { "939-hello-transformation-bcp", common_redefine::OnLoad, nullptr }, { "941-recursive-obsolete-jit", common_redefine::OnLoad, nullptr }, { "943-private-recursive-jit", common_redefine::OnLoad, nullptr }, - { "983-source-transform-verify", Test983SourceTransformVerify::OnLoad, nullptr }, { "1919-vminit-thread-start-timing", Test1919VMInitThreadStart::OnLoad, nullptr }, }; |