diff options
author | Andreas Gampe <agampe@google.com> | 2015-05-22 18:31:50 -0700 |
---|---|---|
committer | Andreas Gampe <agampe@google.com> | 2015-05-31 16:59:11 -0700 |
commit | 8ee2145d65ed14b267ae4c6396f2333115611a97 (patch) | |
tree | 77c4ffa7f2b21e35e9e09bbce26306ca486f64e2 /test/115-native-bridge | |
parent | 93de952df65ca5033bda313712b68b6272b4975f (diff) | |
download | art-8ee2145d65ed14b267ae4c6396f2333115611a97.zip art-8ee2145d65ed14b267ae4c6396f2333115611a97.tar.gz art-8ee2145d65ed14b267ae4c6396f2333115611a97.tar.bz2 |
ART: Add support for special handlers in sigchainlib
Add support for a special managed handler in sigchainlib that
will be called as the first user handler.
Use this support for native bridge v2. Extend test 115-native-bridge
to test the functionality.
Bug: 20217701
(cherry picked from commit 03c2cc89428914adf52229d6a3867eef6127911a)
Change-Id: I78cc01fbdabe169154ff6b94c9f3ddb95b5c7448
Diffstat (limited to 'test/115-native-bridge')
-rw-r--r-- | test/115-native-bridge/expected.txt | 5 | ||||
-rw-r--r-- | test/115-native-bridge/nativebridge.cc | 97 | ||||
-rw-r--r-- | test/115-native-bridge/src/NativeBridgeMain.java | 13 |
3 files changed, 111 insertions, 4 deletions
diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt index deb70ba..464d2c8 100644 --- a/test/115-native-bridge/expected.txt +++ b/test/115-native-bridge/expected.txt @@ -4,7 +4,7 @@ Checking for getEnvValues. Ready for native bridge tests. Checking for support. Getting trampoline for JNI_OnLoad with shorty (null). -Test ART callbacks: all JNI function number is 10. +Test ART callbacks: all JNI function number is 11. name:booleanMethod, signature:(ZZZZZZZZZZ)Z, shorty:ZZZZZZZZZZZ. name:byteMethod, signature:(BBBBBBBBBB)B, shorty:BBBBBBBBBBB. name:charMethod, signature:(CCCCCCCCCC)C, shorty:CCCCCCCCCCC. @@ -14,6 +14,7 @@ Test ART callbacks: all JNI function number is 10. name:testFindFieldOnAttachedNativeThreadNative, signature:()V, shorty:V. name:testGetMirandaMethodNative, signature:()Ljava/lang/reflect/Method;, shorty:L. name:testNewStringObject, signature:()V, shorty:V. + name:testSignal, signature:()I, shorty:I. name:testZeroLengthByteBuffers, signature:()V, shorty:V. trampoline_JNI_OnLoad called! Getting trampoline for Java_Main_testFindClassOnAttachedNativeThread with shorty V. @@ -58,3 +59,5 @@ trampoline_Java_Main_charMethod called! trampoline_Java_Main_charMethod called! Getting trampoline for Java_Main_testNewStringObject with shorty V. trampoline_Java_Main_testNewStringObject called! +Getting trampoline for Java_Main_testSignal with shorty I. +NB signal handler with signal 11. diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc index db2fc9b..fd94b23 100644 --- a/test/115-native-bridge/nativebridge.cc +++ b/test/115-native-bridge/nativebridge.cc @@ -19,6 +19,8 @@ #include <algorithm> #include <dlfcn.h> #include <jni.h> +#include <stdlib.h> +#include <signal.h> #include <vector> #include "stdio.h" @@ -179,6 +181,35 @@ static jchar trampoline_Java_Main_charMethod(JNIEnv* env, jclass klass, jchar c1 return fnPtr(env, klass, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10); } +// This code is adapted from 004-SignalTest and causes a segfault. +char *go_away_compiler = nullptr; + +[[ noreturn ]] static void test_sigaction_handler(int sig ATTRIBUTE_UNUSED, + siginfo_t* info ATTRIBUTE_UNUSED, + void* context ATTRIBUTE_UNUSED) { + printf("Should not reach the test sigaction handler."); + abort(); +} + +static jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) { + // Install the sigaction handler above, which should *not* be reached as the native-bridge + // handler should be called first. Note: we won't chain at all, if we ever get here, we'll die. + struct sigaction tmp; + sigemptyset(&tmp.sa_mask); + tmp.sa_sigaction = test_sigaction_handler; + tmp.sa_restorer = nullptr; + sigaction(SIGSEGV, &tmp, nullptr); + +#if defined(__arm__) || defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) + // On supported architectures we cause a real SEGV. + *go_away_compiler = 'a'; +#else + // On other architectures we simulate SEGV. + kill(getpid(), SIGSEGV); +#endif + return 1234; +} + NativeBridgeMethod gNativeBridgeMethods[] = { { "JNI_OnLoad", "", true, nullptr, reinterpret_cast<void*>(trampoline_JNI_OnLoad) }, @@ -202,6 +233,8 @@ NativeBridgeMethod gNativeBridgeMethods[] = { reinterpret_cast<void*>(trampoline_Java_Main_testNewStringObject) }, { "testZeroLengthByteBuffers", "()V", true, nullptr, reinterpret_cast<void*>(trampoline_Java_Main_testZeroLengthByteBuffers) }, + { "testSignal", "()I", true, nullptr, + reinterpret_cast<void*>(trampoline_Java_Main_testSignal) }, }; static NativeBridgeMethod* find_native_bridge_method(const char *name) { @@ -319,15 +352,73 @@ extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getApp return &nb_env; } +// v2 parts. + +extern "C" bool nb_is_compatible(uint32_t bridge_version ATTRIBUTE_UNUSED) { + return true; +} + +#if defined(__i386__) || defined(__x86_64__) +#if defined(__APPLE__) +#define ucontext __darwin_ucontext + +#if defined(__x86_64__) +// 64 bit mac build. +#define CTX_EIP uc_mcontext->__ss.__rip +#else +// 32 bit mac build. +#define CTX_EIP uc_mcontext->__ss.__eip +#endif + +#elif defined(__x86_64__) +// 64 bit linux build. +#define CTX_EIP uc_mcontext.gregs[REG_RIP] +#else +// 32 bit linux build. +#define CTX_EIP uc_mcontext.gregs[REG_EIP] +#endif +#endif + +// A dummy special handler, continueing after the faulting location. This code comes from +// 004-SignalTest. +static bool nb_signalhandler(int sig, siginfo_t* info ATTRIBUTE_UNUSED, void* context) { + printf("NB signal handler with signal %d.\n", sig); +#if defined(__arm__) + struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); + struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext); + sc->arm_pc += 2; // Skip instruction causing segv. +#elif defined(__aarch64__) + struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); + struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext); + sc->pc += 4; // Skip instruction causing segv. +#elif defined(__i386__) || defined(__x86_64__) + struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); + uc->CTX_EIP += 3; +#else + UNUSED(context); +#endif + // We handled this... + return true; +} + +static ::android::NativeBridgeSignalHandlerFn native_bridge_get_signal_handler(int signal) { + // Only test segfault handler. + if (signal == SIGSEGV) { + return &nb_signalhandler; + } + return nullptr; +} + + // "NativeBridgeItf" is effectively an API (it is the name of the symbol that will be loaded // by the native bridge library). android::NativeBridgeCallbacks NativeBridgeItf { - .version = 1, + .version = 2, .initialize = &native_bridge_initialize, .loadLibrary = &native_bridge_loadLibrary, .getTrampoline = &native_bridge_getTrampoline, .isSupported = &native_bridge_isSupported, .getAppEnv = &native_bridge_getAppEnv, - .isCompatibleWith = nullptr, - .getSignalHandler = nullptr + .isCompatibleWith = &nb_is_compatible, + .getSignalHandler = &native_bridge_get_signal_handler }; diff --git a/test/115-native-bridge/src/NativeBridgeMain.java b/test/115-native-bridge/src/NativeBridgeMain.java index c843707..25390f7 100644 --- a/test/115-native-bridge/src/NativeBridgeMain.java +++ b/test/115-native-bridge/src/NativeBridgeMain.java @@ -32,6 +32,7 @@ class Main { testCharMethod(); testEnvironment(); testNewStringObject(); + testSignalHandler(); } public static native void testFindClassOnAttachedNativeThread(); @@ -170,6 +171,18 @@ class Main { } private static native void testNewStringObject(); + + // Test v2 special signal handlers. This uses the native code from 004-SignalTest to cause + // a non-managed segfault. + private static void testSignalHandler() { + // This uses code from 004-SignalTest. + int x = testSignal(); + if (x != 1234) { + throw new AssertionError(); + } + } + + private static native int testSignal(); } public class NativeBridgeMain { |