1855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe/* 2855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * Copyright (C) 2014 The Android Open Source Project 3855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * 4855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * Licensed under the Apache License, Version 2.0 (the "License"); 5855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * you may not use this file except in compliance with the License. 6855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * You may obtain a copy of the License at 7855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * 8855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * http://www.apache.org/licenses/LICENSE-2.0 9855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * 10855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * Unless required by applicable law or agreed to in writing, software 11855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * distributed under the License is distributed on an "AS IS" BASIS, 12855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * See the License for the specific language governing permissions and 14855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe * limitations under the License. 15855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe */ 16855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 17855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe// A simple implementation of the native-bridge interface. 18855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 19855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe#include <algorithm> 20855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe#include <dlfcn.h> 216a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#include <jni.h> 2203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#include <stdlib.h> 2303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#include <signal.h> 24855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe#include <vector> 25855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 26855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe#include "stdio.h" 27855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe#include "unistd.h" 2844a3506627833deb17d21d6a7d51245a5af2c3e9Calin Juravle#include "sys/stat.h" 29855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 306a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers#include "base/macros.h" 31c8423521c1d1136c70b153479b7df3bf4fd7fc2aCalin Juravle#include "nativebridge/native_bridge.h" 32855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 33f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstruct NativeBridgeMethod { 34f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU const char* name; 35f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU const char* signature; 36f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU bool static_method; 37f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU void* fnPtr; 38f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU void* trampoline; 39f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU}; 40f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 41f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic NativeBridgeMethod* find_native_bridge_method(const char *name); 42c8423521c1d1136c70b153479b7df3bf4fd7fc2aCalin Juravlestatic const android::NativeBridgeRuntimeCallbacks* gNativeBridgeArtCallbacks; 43f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 44f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic jint trampoline_JNI_OnLoad(JavaVM* vm, void* reserved) { 45f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU JNIEnv* env = nullptr; 46f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef jint (*FnPtr_t)(JavaVM*, void*); 47f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("JNI_OnLoad")->fnPtr); 48f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 49f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6); 50f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (env == nullptr) { 51f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return 0; 52f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 53f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 54f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jclass klass = env->FindClass("Main"); 55f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (klass != nullptr) { 56f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU int i, count1, count2; 57f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU count1 = gNativeBridgeArtCallbacks->getNativeMethodCount(env, klass); 58f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU std::unique_ptr<JNINativeMethod[]> methods(new JNINativeMethod[count1]); 59f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (methods == nullptr) { 60f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return 0; 61f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 62f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU count2 = gNativeBridgeArtCallbacks->getNativeMethods(env, klass, methods.get(), count1); 63f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (count1 == count2) { 64f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("Test ART callbacks: all JNI function number is %d.\n", count1); 65f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 66f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 67f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU for (i = 0; i < count1; i++) { 68f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU NativeBridgeMethod* nb_method = find_native_bridge_method(methods[i].name); 69f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (nb_method != nullptr) { 70f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jmethodID mid = nullptr; 71f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (nb_method->static_method) { 72f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU mid = env->GetStaticMethodID(klass, methods[i].name, nb_method->signature); 73f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } else { 74f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU mid = env->GetMethodID(klass, methods[i].name, nb_method->signature); 75f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 76f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (mid != nullptr) { 77f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU const char* shorty = gNativeBridgeArtCallbacks->getMethodShorty(env, mid); 78f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (strcmp(shorty, methods[i].signature) == 0) { 79f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf(" name:%s, signature:%s, shorty:%s.\n", 80f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU methods[i].name, nb_method->signature, shorty); 81f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 82f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 83f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 84f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 85f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU methods.release(); 86f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 87f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 88f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 89f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(vm, reserved); 90f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 91f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 92f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic void trampoline_Java_Main_testFindClassOnAttachedNativeThread(JNIEnv* env, 93f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jclass klass) { 94f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef void (*FnPtr_t)(JNIEnv*, jclass); 95f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 96f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU (find_native_bridge_method("testFindClassOnAttachedNativeThread")->fnPtr); 97f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 98f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(env, klass); 99f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 100f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 101f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic void trampoline_Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv* env, 102f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jclass klass) { 103f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef void (*FnPtr_t)(JNIEnv*, jclass); 104f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 105f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU (find_native_bridge_method("testFindFieldOnAttachedNativeThreadNative")->fnPtr); 106f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 107f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(env, klass); 108f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 109f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 110f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic void trampoline_Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env, 111f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jclass klass) { 112f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef void (*FnPtr_t)(JNIEnv*, jclass); 113f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 114f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU (find_native_bridge_method("testCallStaticVoidMethodOnSubClassNative")->fnPtr); 115f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 116f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(env, klass); 117f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 118f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 119f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic jobject trampoline_Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass klass) { 120f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef jobject (*FnPtr_t)(JNIEnv*, jclass); 121f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 122f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU (find_native_bridge_method("testGetMirandaMethodNative")->fnPtr); 123f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 124f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(env, klass); 125f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 126855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 127848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Haostatic void trampoline_Java_Main_testNewStringObject(JNIEnv* env, jclass klass) { 128848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao typedef void (*FnPtr_t)(JNIEnv*, jclass); 129848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 130848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao (find_native_bridge_method("testNewStringObject")->fnPtr); 131848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao printf("%s called!\n", __FUNCTION__); 132848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao return fnPtr(env, klass); 133848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao} 134848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao 135f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic void trampoline_Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass klass) { 136f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef void (*FnPtr_t)(JNIEnv*, jclass); 137f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 138f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU (find_native_bridge_method("testZeroLengthByteBuffers")->fnPtr); 139f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 140f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(env, klass); 141f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 142f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 143f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic jbyte trampoline_Java_Main_byteMethod(JNIEnv* env, jclass klass, jbyte b1, jbyte b2, 144f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jbyte b3, jbyte b4, jbyte b5, jbyte b6, 145f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jbyte b7, jbyte b8, jbyte b9, jbyte b10) { 146f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef jbyte (*FnPtr_t)(JNIEnv*, jclass, jbyte, jbyte, jbyte, jbyte, jbyte, 147f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jbyte, jbyte, jbyte, jbyte, jbyte); 148f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("byteMethod")->fnPtr); 149f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 150f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(env, klass, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10); 151f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 152855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 153f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic jshort trampoline_Java_Main_shortMethod(JNIEnv* env, jclass klass, jshort s1, jshort s2, 154f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jshort s3, jshort s4, jshort s5, jshort s6, 155f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jshort s7, jshort s8, jshort s9, jshort s10) { 156f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef jshort (*FnPtr_t)(JNIEnv*, jclass, jshort, jshort, jshort, jshort, jshort, 157f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jshort, jshort, jshort, jshort, jshort); 158f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("shortMethod")->fnPtr); 159f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 160f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(env, klass, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10); 161f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 162f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 163f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic jboolean trampoline_Java_Main_booleanMethod(JNIEnv* env, jclass klass, jboolean b1, 164f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jboolean b2, jboolean b3, jboolean b4, 165f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jboolean b5, jboolean b6, jboolean b7, 166f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jboolean b8, jboolean b9, jboolean b10) { 167f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef jboolean (*FnPtr_t)(JNIEnv*, jclass, jboolean, jboolean, jboolean, jboolean, jboolean, 168f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jboolean, jboolean, jboolean, jboolean, jboolean); 169f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("booleanMethod")->fnPtr); 170f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 171f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(env, klass, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10); 172f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 173f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 174f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic jchar trampoline_Java_Main_charMethod(JNIEnv* env, jclass klass, jchar c1, jchar c2, 175f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jchar c3, jchar c4, jchar c5, jchar c6, 176f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jchar c7, jchar c8, jchar c9, jchar c10) { 177f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU typedef jchar (*FnPtr_t)(JNIEnv*, jclass, jchar, jchar, jchar, jchar, jchar, 178f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU jchar, jchar, jchar, jchar, jchar); 179f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("charMethod")->fnPtr); 180f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("%s called!\n", __FUNCTION__); 181f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return fnPtr(env, klass, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10); 182f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 183f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 18403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe// This code is adapted from 004-SignalTest and causes a segfault. 18503c2cc89428914adf52229d6a3867eef6127911aAndreas Gampechar *go_away_compiler = nullptr; 18603c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 18703c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe[[ noreturn ]] static void test_sigaction_handler(int sig ATTRIBUTE_UNUSED, 18803c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe siginfo_t* info ATTRIBUTE_UNUSED, 18903c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe void* context ATTRIBUTE_UNUSED) { 19003c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe printf("Should not reach the test sigaction handler."); 19103c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe abort(); 19203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe} 19303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 19403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampestatic jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) { 19503c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe // Install the sigaction handler above, which should *not* be reached as the native-bridge 19603c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe // handler should be called first. Note: we won't chain at all, if we ever get here, we'll die. 19703c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe struct sigaction tmp; 19803c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe sigemptyset(&tmp.sa_mask); 19903c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe tmp.sa_sigaction = test_sigaction_handler; 200d0af5479d61013362e43ae15cb69c9f8da915e08Douglas Leung#if !defined(__APPLE__) && !defined(__mips__) 20103c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe tmp.sa_restorer = nullptr; 202d0af5479d61013362e43ae15cb69c9f8da915e08Douglas Leung#endif 20303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 2040c7c55c717e774598ebce25f662209e8db23b3c9jgu // Test segv 2050c7c55c717e774598ebce25f662209e8db23b3c9jgu sigaction(SIGSEGV, &tmp, nullptr); 2063996c89a49238037e852203e74b026015608fb0aAgi Csaki#if defined(__arm__) || defined(__i386__) || defined(__aarch64__) 20703c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe *go_away_compiler = 'a'; 2083996c89a49238037e852203e74b026015608fb0aAgi Csaki#elif defined(__x86_64__) 209fd2854137ebdd2dbcc1459c5aa7abccdc62691b2Andreas Gampe // Cause a SEGV using an instruction known to be 2 bytes long to account for hardcoded jump 2103835acca9101bd7afa181d8df8eba5a496d480e6Agi Csaki // in the signal handler 211fd2854137ebdd2dbcc1459c5aa7abccdc62691b2Andreas Gampe asm volatile("movl $0, %%eax;" "movb %%ah, (%%rax);" : : : "%eax"); 21203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#else 21303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe // On other architectures we simulate SEGV. 21403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe kill(getpid(), SIGSEGV); 21503c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#endif 2160c7c55c717e774598ebce25f662209e8db23b3c9jgu 2170c7c55c717e774598ebce25f662209e8db23b3c9jgu // Test sigill 2180c7c55c717e774598ebce25f662209e8db23b3c9jgu sigaction(SIGILL, &tmp, nullptr); 2190c7c55c717e774598ebce25f662209e8db23b3c9jgu kill(getpid(), SIGILL); 2200c7c55c717e774598ebce25f662209e8db23b3c9jgu 22103c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe return 1234; 22203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe} 22303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 224f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUNativeBridgeMethod gNativeBridgeMethods[] = { 225f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "JNI_OnLoad", "", true, nullptr, 226f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_JNI_OnLoad) }, 227f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "booleanMethod", "(ZZZZZZZZZZ)Z", true, nullptr, 228f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_Java_Main_booleanMethod) }, 229f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "byteMethod", "(BBBBBBBBBB)B", true, nullptr, 230f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_Java_Main_byteMethod) }, 231f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "charMethod", "(CCCCCCCCCC)C", true, nullptr, 232f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_Java_Main_charMethod) }, 233f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "shortMethod", "(SSSSSSSSSS)S", true, nullptr, 234f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_Java_Main_shortMethod) }, 235f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "testCallStaticVoidMethodOnSubClassNative", "()V", true, nullptr, 236f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_Java_Main_testCallStaticVoidMethodOnSubClassNative) }, 237f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "testFindClassOnAttachedNativeThread", "()V", true, nullptr, 238f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_Java_Main_testFindClassOnAttachedNativeThread) }, 239f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "testFindFieldOnAttachedNativeThreadNative", "()V", true, nullptr, 240f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_Java_Main_testFindFieldOnAttachedNativeThreadNative) }, 241f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "testGetMirandaMethodNative", "()Ljava/lang/reflect/Method;", true, nullptr, 242f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_Java_Main_testGetMirandaMethodNative) }, 243848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao { "testNewStringObject", "()V", true, nullptr, 244848f70a3d73833fc1bf3032a9ff6812e429661d9Jeff Hao reinterpret_cast<void*>(trampoline_Java_Main_testNewStringObject) }, 245f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU { "testZeroLengthByteBuffers", "()V", true, nullptr, 246f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU reinterpret_cast<void*>(trampoline_Java_Main_testZeroLengthByteBuffers) }, 24703c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe { "testSignal", "()I", true, nullptr, 24803c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe reinterpret_cast<void*>(trampoline_Java_Main_testSignal) }, 249f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU}; 250f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 251f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WUstatic NativeBridgeMethod* find_native_bridge_method(const char *name) { 252f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU const char* pname = name; 253f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (strncmp(name, "Java_Main_", 10) == 0) { 254f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU pname += 10; 255f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 256f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU 257f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU for (size_t i = 0; i < sizeof(gNativeBridgeMethods) / sizeof(gNativeBridgeMethods[0]); i++) { 258f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (strcmp(pname, gNativeBridgeMethods[i].name) == 0) { 259f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return &gNativeBridgeMethods[i]; 260f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 261f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 262f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return nullptr; 263f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU} 264855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 265855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe// NativeBridgeCallbacks implementations 266a6da74e941d7cee498ac3880018a1d8dc953c6ebjguextern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* art_cbs, 2676a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers const char* app_code_cache_dir, 2686a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers const char* isa ATTRIBUTE_UNUSED) { 26944a3506627833deb17d21d6a7d51245a5af2c3e9Calin Juravle struct stat st; 270ef885cdfa8e3c61a67750110c1efcdd2559af1ecCalin Juravle if (app_code_cache_dir != nullptr) { 271ef885cdfa8e3c61a67750110c1efcdd2559af1ecCalin Juravle if (stat(app_code_cache_dir, &st) == 0) { 272eda4dfae59eec2db945cf032aee3a9aeaa2eb494Calin Juravle if (!S_ISDIR(st.st_mode)) { 273ef885cdfa8e3c61a67750110c1efcdd2559af1ecCalin Juravle printf("Code cache is not a directory.\n"); 274ef885cdfa8e3c61a67750110c1efcdd2559af1ecCalin Juravle } 275ef885cdfa8e3c61a67750110c1efcdd2559af1ecCalin Juravle } else { 276ef885cdfa8e3c61a67750110c1efcdd2559af1ecCalin Juravle perror("Error when stat-ing the code_cache:"); 277ef885cdfa8e3c61a67750110c1efcdd2559af1ecCalin Juravle } 27844a3506627833deb17d21d6a7d51245a5af2c3e9Calin Juravle } 279ef885cdfa8e3c61a67750110c1efcdd2559af1ecCalin Juravle 280f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (art_cbs != nullptr) { 281f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU gNativeBridgeArtCallbacks = art_cbs; 282f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("Native bridge initialized.\n"); 283f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU } 284855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe return true; 285855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe} 286855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 287855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampeextern "C" void* native_bridge_loadLibrary(const char* libpath, int flag) { 288855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe size_t len = strlen(libpath); 289855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe char* tmp = new char[len + 10]; 290855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe strncpy(tmp, libpath, len); 291855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe tmp[len - 3] = '2'; 292855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe tmp[len - 2] = '.'; 293855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe tmp[len - 1] = 's'; 294855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe tmp[len] = 'o'; 295855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe tmp[len + 1] = 0; 296855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe void* handle = dlopen(tmp, flag); 297855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe delete[] tmp; 298855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 299855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe if (handle == nullptr) { 300855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe printf("Handle = nullptr!\n"); 301855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe printf("Was looking for %s.\n", libpath); 302855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe printf("Error = %s.\n", dlerror()); 303855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe char cwd[1024]; 304855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe if (getcwd(cwd, sizeof(cwd)) != nullptr) { 305855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe printf("Current working dir: %s\n", cwd); 306855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe } 307855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe } 308855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe return handle; 309855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe} 310855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 311855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampeextern "C" void* native_bridge_getTrampoline(void* handle, const char* name, const char* shorty, 3126a3c1fcb4ba42ad4d5d142c17a3712a6ddd3866fIan Rogers uint32_t len ATTRIBUTE_UNUSED) { 313f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU printf("Getting trampoline for %s with shorty %s.\n", name, shorty); 314855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 315855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe // The name here is actually the JNI name, so we can directly do the lookup. 316855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe void* sym = dlsym(handle, name); 317f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU NativeBridgeMethod* method = find_native_bridge_method(name); 318f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU if (method == nullptr) 319f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return nullptr; 320f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU method->fnPtr = sym; 321855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 322f7a68c1bd01db4e80003eb19cc8a4cdc8330adbeYong WU return method->trampoline; 323855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe} 324855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 325855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampeextern "C" bool native_bridge_isSupported(const char* libpath) { 326855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe printf("Checking for support.\n"); 327855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 328855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe if (libpath == nullptr) { 329855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe return false; 330855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe } 331855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe // We don't want to hijack javacore. So we should get libarttest... 332855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe return strcmp(libpath, "libjavacore.so") != 0; 333855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe} 334855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe 335a6da74e941d7cee498ac3880018a1d8dc953c6ebjgunamespace android { 336a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu 337a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu// Environment values required by the apps running with native bridge. 338a6da74e941d7cee498ac3880018a1d8dc953c6ebjgustruct NativeBridgeRuntimeValues { 339a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu const char* os_arch; 340a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu const char* cpu_abi; 341a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu const char* cpu_abi2; 342a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu const char* *supported_abis; 343a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu int32_t abi_count; 344a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu}; 345a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu 346a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu} // namespace android 347a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu 348a6da74e941d7cee498ac3880018a1d8dc953c6ebjguconst char* supported_abis[] = { 349a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu "supported1", "supported2", "supported3" 350a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu}; 351a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu 352a6da74e941d7cee498ac3880018a1d8dc953c6ebjguconst struct android::NativeBridgeRuntimeValues nb_env { 353a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu .os_arch = "os.arch", 354a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu .cpu_abi = "cpu_abi", 355a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu .cpu_abi2 = "cpu_abi2", 356a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu .supported_abis = supported_abis, 357a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu .abi_count = 3 358a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu}; 359a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu 360a6da74e941d7cee498ac3880018a1d8dc953c6ebjguextern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv( 361a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu const char* abi) { 362a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu printf("Checking for getEnvValues.\n"); 363a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu 364a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu if (abi == nullptr) { 365a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu return nullptr; 366a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu } 367a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu 368a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu return &nb_env; 369a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu} 370a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu 37103c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe// v2 parts. 37203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 37303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampeextern "C" bool nb_is_compatible(uint32_t bridge_version ATTRIBUTE_UNUSED) { 37403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe return true; 37503c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe} 37603c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 37703c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#if defined(__i386__) || defined(__x86_64__) 37803c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#if defined(__APPLE__) 37903c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#define ucontext __darwin_ucontext 38003c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 38103c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#if defined(__x86_64__) 38203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe// 64 bit mac build. 38303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#define CTX_EIP uc_mcontext->__ss.__rip 38403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#else 38503c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe// 32 bit mac build. 38603c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#define CTX_EIP uc_mcontext->__ss.__eip 38703c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#endif 38803c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 38903c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#elif defined(__x86_64__) 39003c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe// 64 bit linux build. 39103c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#define CTX_EIP uc_mcontext.gregs[REG_RIP] 39203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#else 39303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe// 32 bit linux build. 39403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#define CTX_EIP uc_mcontext.gregs[REG_EIP] 39503c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#endif 39603c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#endif 39703c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 3980d6f02679111fc1dd84cc45ddb4daab2fc622911jgustatic bool cannot_be_blocked(int signum) { 3990d6f02679111fc1dd84cc45ddb4daab2fc622911jgu // These two sigs cannot be blocked anywhere. 4000d6f02679111fc1dd84cc45ddb4daab2fc622911jgu if ((signum == SIGKILL) || (signum == SIGSTOP)) { 4010d6f02679111fc1dd84cc45ddb4daab2fc622911jgu return true; 4020d6f02679111fc1dd84cc45ddb4daab2fc622911jgu } 4030d6f02679111fc1dd84cc45ddb4daab2fc622911jgu 4040d6f02679111fc1dd84cc45ddb4daab2fc622911jgu // The invalid rt_sig cannot be blocked. 4050d6f02679111fc1dd84cc45ddb4daab2fc622911jgu if (((signum >= 32) && (signum < SIGRTMIN)) || (signum > SIGRTMAX)) { 4060d6f02679111fc1dd84cc45ddb4daab2fc622911jgu return true; 4070d6f02679111fc1dd84cc45ddb4daab2fc622911jgu } 4080d6f02679111fc1dd84cc45ddb4daab2fc622911jgu 4090d6f02679111fc1dd84cc45ddb4daab2fc622911jgu return false; 4100d6f02679111fc1dd84cc45ddb4daab2fc622911jgu} 4110d6f02679111fc1dd84cc45ddb4daab2fc622911jgu 41203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe// A dummy special handler, continueing after the faulting location. This code comes from 41303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe// 004-SignalTest. 41403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampestatic bool nb_signalhandler(int sig, siginfo_t* info ATTRIBUTE_UNUSED, void* context) { 41503c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe printf("NB signal handler with signal %d.\n", sig); 4160c7c55c717e774598ebce25f662209e8db23b3c9jgu if (sig == SIGSEGV) { 41703c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#if defined(__arm__) 4180c7c55c717e774598ebce25f662209e8db23b3c9jgu struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 4190c7c55c717e774598ebce25f662209e8db23b3c9jgu struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext); 4200c7c55c717e774598ebce25f662209e8db23b3c9jgu sc->arm_pc += 2; // Skip instruction causing segv & sigill. 42103c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#elif defined(__aarch64__) 4220c7c55c717e774598ebce25f662209e8db23b3c9jgu struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 4230c7c55c717e774598ebce25f662209e8db23b3c9jgu struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext); 4240c7c55c717e774598ebce25f662209e8db23b3c9jgu sc->pc += 4; // Skip instruction causing segv & sigill. 425fd2854137ebdd2dbcc1459c5aa7abccdc62691b2Andreas Gampe#elif defined(__i386__) 4260c7c55c717e774598ebce25f662209e8db23b3c9jgu struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 4270c7c55c717e774598ebce25f662209e8db23b3c9jgu uc->CTX_EIP += 3; 428fd2854137ebdd2dbcc1459c5aa7abccdc62691b2Andreas Gampe#elif defined(__x86_64__) 429fd2854137ebdd2dbcc1459c5aa7abccdc62691b2Andreas Gampe struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 430fd2854137ebdd2dbcc1459c5aa7abccdc62691b2Andreas Gampe uc->CTX_EIP += 2; 43103c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#else 4320c7c55c717e774598ebce25f662209e8db23b3c9jgu UNUSED(context); 43303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe#endif 4340c7c55c717e774598ebce25f662209e8db23b3c9jgu } 4350d6f02679111fc1dd84cc45ddb4daab2fc622911jgu 4360d6f02679111fc1dd84cc45ddb4daab2fc622911jgu // Before invoking this handler, all other unclaimed signals must be blocked. 4370d6f02679111fc1dd84cc45ddb4daab2fc622911jgu // We're trying to check the signal mask to verify its status here. 4380d6f02679111fc1dd84cc45ddb4daab2fc622911jgu sigset_t tmpset; 4390d6f02679111fc1dd84cc45ddb4daab2fc622911jgu sigemptyset(&tmpset); 4400d6f02679111fc1dd84cc45ddb4daab2fc622911jgu sigprocmask(SIG_SETMASK, nullptr, &tmpset); 4410d6f02679111fc1dd84cc45ddb4daab2fc622911jgu int other_claimed = (sig == SIGSEGV) ? SIGILL : SIGSEGV; 4420d6f02679111fc1dd84cc45ddb4daab2fc622911jgu for (int signum = 0; signum < NSIG; ++signum) { 4430d6f02679111fc1dd84cc45ddb4daab2fc622911jgu if (cannot_be_blocked(signum)) { 4440d6f02679111fc1dd84cc45ddb4daab2fc622911jgu continue; 4450d6f02679111fc1dd84cc45ddb4daab2fc622911jgu } else if ((sigismember(&tmpset, signum)) && (signum == other_claimed)) { 4460d6f02679111fc1dd84cc45ddb4daab2fc622911jgu printf("ERROR: The claimed signal %d is blocked\n", signum); 4470d6f02679111fc1dd84cc45ddb4daab2fc622911jgu } else if ((!sigismember(&tmpset, signum)) && (signum != other_claimed)) { 4480d6f02679111fc1dd84cc45ddb4daab2fc622911jgu printf("ERROR: The unclaimed signal %d is not blocked\n", signum); 4490d6f02679111fc1dd84cc45ddb4daab2fc622911jgu } 4500d6f02679111fc1dd84cc45ddb4daab2fc622911jgu } 4510d6f02679111fc1dd84cc45ddb4daab2fc622911jgu 45203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe // We handled this... 45303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe return true; 45403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe} 45503c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 45603c2cc89428914adf52229d6a3867eef6127911aAndreas Gampestatic ::android::NativeBridgeSignalHandlerFn native_bridge_get_signal_handler(int signal) { 4570c7c55c717e774598ebce25f662209e8db23b3c9jgu // Test segv for already claimed signal, and sigill for not claimed signal 4580c7c55c717e774598ebce25f662209e8db23b3c9jgu if ((signal == SIGSEGV) || (signal == SIGILL)) { 45903c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe return &nb_signalhandler; 46003c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe } 46103c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe return nullptr; 46203c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe} 46303c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 46403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe 465c8423521c1d1136c70b153479b7df3bf4fd7fc2aCalin Juravle// "NativeBridgeItf" is effectively an API (it is the name of the symbol that will be loaded 466c8423521c1d1136c70b153479b7df3bf4fd7fc2aCalin Juravle// by the native bridge library). 467c8423521c1d1136c70b153479b7df3bf4fd7fc2aCalin Juravleandroid::NativeBridgeCallbacks NativeBridgeItf { 46803c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe .version = 2, 469855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe .initialize = &native_bridge_initialize, 470855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe .loadLibrary = &native_bridge_loadLibrary, 471855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe .getTrampoline = &native_bridge_getTrampoline, 472a6da74e941d7cee498ac3880018a1d8dc953c6ebjgu .isSupported = &native_bridge_isSupported, 473540cc3d49c858e670591d8c00fcd87576cdbede6Andreas Gampe .getAppEnv = &native_bridge_getAppEnv, 47403c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe .isCompatibleWith = &nb_is_compatible, 47503c2cc89428914adf52229d6a3867eef6127911aAndreas Gampe .getSignalHandler = &native_bridge_get_signal_handler 476855564b83db7b106d2995d0e784f1f4b62e52371Andreas Gampe}; 477