summaryrefslogtreecommitdiffstats
path: root/test/115-native-bridge
diff options
context:
space:
mode:
authorAndreas Gampe <agampe@google.com>2015-05-22 18:31:50 -0700
committerAndreas Gampe <agampe@google.com>2015-05-31 16:59:11 -0700
commit8ee2145d65ed14b267ae4c6396f2333115611a97 (patch)
tree77c4ffa7f2b21e35e9e09bbce26306ca486f64e2 /test/115-native-bridge
parent93de952df65ca5033bda313712b68b6272b4975f (diff)
downloadart-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.txt5
-rw-r--r--test/115-native-bridge/nativebridge.cc97
-rw-r--r--test/115-native-bridge/src/NativeBridgeMain.java13
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 {