1 /* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 // A simple implementation of the native-bridge interface. 18 19 #include <algorithm> 20 #include <dlfcn.h> 21 #include <jni.h> 22 #include <stdlib.h> 23 #include <signal.h> 24 #include <vector> 25 26 #include "stdio.h" 27 #include "unistd.h" 28 #include "sys/stat.h" 29 30 #include "base/macros.h" 31 #include "nativebridge/native_bridge.h" 32 33 struct NativeBridgeMethod { 34 const char* name; 35 const char* signature; 36 bool static_method; 37 void* fnPtr; 38 void* trampoline; 39 }; 40 41 static NativeBridgeMethod* find_native_bridge_method(const char *name); 42 static const android::NativeBridgeRuntimeCallbacks* gNativeBridgeArtCallbacks; 43 44 static jint trampoline_JNI_OnLoad(JavaVM* vm, void* reserved) { 45 JNIEnv* env = nullptr; 46 typedef jint (*FnPtr_t)(JavaVM*, void*); 47 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("JNI_OnLoad")->fnPtr); 48 49 vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6); 50 if (env == nullptr) { 51 return 0; 52 } 53 54 jclass klass = env->FindClass("Main"); 55 if (klass != nullptr) { 56 int i, count1, count2; 57 count1 = gNativeBridgeArtCallbacks->getNativeMethodCount(env, klass); 58 std::unique_ptr<JNINativeMethod[]> methods(new JNINativeMethod[count1]); 59 if (methods == nullptr) { 60 return 0; 61 } 62 count2 = gNativeBridgeArtCallbacks->getNativeMethods(env, klass, methods.get(), count1); 63 if (count1 == count2) { 64 printf("Test ART callbacks: all JNI function number is %d.\n", count1); 65 } 66 67 for (i = 0; i < count1; i++) { 68 NativeBridgeMethod* nb_method = find_native_bridge_method(methods[i].name); 69 if (nb_method != nullptr) { 70 jmethodID mid = nullptr; 71 if (nb_method->static_method) { 72 mid = env->GetStaticMethodID(klass, methods[i].name, nb_method->signature); 73 } else { 74 mid = env->GetMethodID(klass, methods[i].name, nb_method->signature); 75 } 76 if (mid != nullptr) { 77 const char* shorty = gNativeBridgeArtCallbacks->getMethodShorty(env, mid); 78 if (strcmp(shorty, methods[i].signature) == 0) { 79 printf(" name:%s, signature:%s, shorty:%s.\n", 80 methods[i].name, nb_method->signature, shorty); 81 } 82 } 83 } 84 } 85 methods.release(); 86 } 87 88 printf("%s called!\n", __FUNCTION__); 89 return fnPtr(vm, reserved); 90 } 91 92 static void trampoline_Java_Main_testFindClassOnAttachedNativeThread(JNIEnv* env, 93 jclass klass) { 94 typedef void (*FnPtr_t)(JNIEnv*, jclass); 95 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 96 (find_native_bridge_method("testFindClassOnAttachedNativeThread")->fnPtr); 97 printf("%s called!\n", __FUNCTION__); 98 return fnPtr(env, klass); 99 } 100 101 static void trampoline_Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv* env, 102 jclass klass) { 103 typedef void (*FnPtr_t)(JNIEnv*, jclass); 104 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 105 (find_native_bridge_method("testFindFieldOnAttachedNativeThreadNative")->fnPtr); 106 printf("%s called!\n", __FUNCTION__); 107 return fnPtr(env, klass); 108 } 109 110 static void trampoline_Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env, 111 jclass klass) { 112 typedef void (*FnPtr_t)(JNIEnv*, jclass); 113 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 114 (find_native_bridge_method("testCallStaticVoidMethodOnSubClassNative")->fnPtr); 115 printf("%s called!\n", __FUNCTION__); 116 return fnPtr(env, klass); 117 } 118 119 static jobject trampoline_Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass klass) { 120 typedef jobject (*FnPtr_t)(JNIEnv*, jclass); 121 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 122 (find_native_bridge_method("testGetMirandaMethodNative")->fnPtr); 123 printf("%s called!\n", __FUNCTION__); 124 return fnPtr(env, klass); 125 } 126 127 static void trampoline_Java_Main_testNewStringObject(JNIEnv* env, jclass klass) { 128 typedef void (*FnPtr_t)(JNIEnv*, jclass); 129 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 130 (find_native_bridge_method("testNewStringObject")->fnPtr); 131 printf("%s called!\n", __FUNCTION__); 132 return fnPtr(env, klass); 133 } 134 135 static void trampoline_Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass klass) { 136 typedef void (*FnPtr_t)(JNIEnv*, jclass); 137 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 138 (find_native_bridge_method("testZeroLengthByteBuffers")->fnPtr); 139 printf("%s called!\n", __FUNCTION__); 140 return fnPtr(env, klass); 141 } 142 143 static jbyte trampoline_Java_Main_byteMethod(JNIEnv* env, jclass klass, jbyte b1, jbyte b2, 144 jbyte b3, jbyte b4, jbyte b5, jbyte b6, 145 jbyte b7, jbyte b8, jbyte b9, jbyte b10) { 146 typedef jbyte (*FnPtr_t)(JNIEnv*, jclass, jbyte, jbyte, jbyte, jbyte, jbyte, 147 jbyte, jbyte, jbyte, jbyte, jbyte); 148 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("byteMethod")->fnPtr); 149 printf("%s called!\n", __FUNCTION__); 150 return fnPtr(env, klass, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10); 151 } 152 153 static jshort trampoline_Java_Main_shortMethod(JNIEnv* env, jclass klass, jshort s1, jshort s2, 154 jshort s3, jshort s4, jshort s5, jshort s6, 155 jshort s7, jshort s8, jshort s9, jshort s10) { 156 typedef jshort (*FnPtr_t)(JNIEnv*, jclass, jshort, jshort, jshort, jshort, jshort, 157 jshort, jshort, jshort, jshort, jshort); 158 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("shortMethod")->fnPtr); 159 printf("%s called!\n", __FUNCTION__); 160 return fnPtr(env, klass, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10); 161 } 162 163 static jboolean trampoline_Java_Main_booleanMethod(JNIEnv* env, jclass klass, jboolean b1, 164 jboolean b2, jboolean b3, jboolean b4, 165 jboolean b5, jboolean b6, jboolean b7, 166 jboolean b8, jboolean b9, jboolean b10) { 167 typedef jboolean (*FnPtr_t)(JNIEnv*, jclass, jboolean, jboolean, jboolean, jboolean, jboolean, 168 jboolean, jboolean, jboolean, jboolean, jboolean); 169 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("booleanMethod")->fnPtr); 170 printf("%s called!\n", __FUNCTION__); 171 return fnPtr(env, klass, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10); 172 } 173 174 static jchar trampoline_Java_Main_charMethod(JNIEnv* env, jclass klass, jchar c1, jchar c2, 175 jchar c3, jchar c4, jchar c5, jchar c6, 176 jchar c7, jchar c8, jchar c9, jchar c10) { 177 typedef jchar (*FnPtr_t)(JNIEnv*, jclass, jchar, jchar, jchar, jchar, jchar, 178 jchar, jchar, jchar, jchar, jchar); 179 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("charMethod")->fnPtr); 180 printf("%s called!\n", __FUNCTION__); 181 return fnPtr(env, klass, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10); 182 } 183 184 // This code is adapted from 004-SignalTest and causes a segfault. 185 char *go_away_compiler = nullptr; 186 187 [[ noreturn ]] static void test_sigaction_handler(int sig ATTRIBUTE_UNUSED, 188 siginfo_t* info ATTRIBUTE_UNUSED, 189 void* context ATTRIBUTE_UNUSED) { 190 printf("Should not reach the test sigaction handler."); 191 abort(); 192 } 193 194 static jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) { 195 // Install the sigaction handler above, which should *not* be reached as the native-bridge 196 // handler should be called first. Note: we won't chain at all, if we ever get here, we'll die. 197 struct sigaction tmp; 198 sigemptyset(&tmp.sa_mask); 199 tmp.sa_sigaction = test_sigaction_handler; 200 #if !defined(__APPLE__) && !defined(__mips__) 201 tmp.sa_restorer = nullptr; 202 #endif 203 204 // Test segv 205 sigaction(SIGSEGV, &tmp, nullptr); 206 #if defined(__arm__) || defined(__i386__) || defined(__aarch64__) 207 *go_away_compiler = 'a'; 208 #elif defined(__x86_64__) 209 // Cause a SEGV using an instruction known to be 2 bytes long to account for hardcoded jump 210 // in the signal handler 211 asm volatile("movl $0, %%eax;" "movb %%ah, (%%rax);" : : : "%eax"); 212 #else 213 // On other architectures we simulate SEGV. 214 kill(getpid(), SIGSEGV); 215 #endif 216 217 // Test sigill 218 sigaction(SIGILL, &tmp, nullptr); 219 kill(getpid(), SIGILL); 220 221 return 1234; 222 } 223 224 NativeBridgeMethod gNativeBridgeMethods[] = { 225 { "JNI_OnLoad", "", true, nullptr, 226 reinterpret_cast<void*>(trampoline_JNI_OnLoad) }, 227 { "booleanMethod", "(ZZZZZZZZZZ)Z", true, nullptr, 228 reinterpret_cast<void*>(trampoline_Java_Main_booleanMethod) }, 229 { "byteMethod", "(BBBBBBBBBB)B", true, nullptr, 230 reinterpret_cast<void*>(trampoline_Java_Main_byteMethod) }, 231 { "charMethod", "(CCCCCCCCCC)C", true, nullptr, 232 reinterpret_cast<void*>(trampoline_Java_Main_charMethod) }, 233 { "shortMethod", "(SSSSSSSSSS)S", true, nullptr, 234 reinterpret_cast<void*>(trampoline_Java_Main_shortMethod) }, 235 { "testCallStaticVoidMethodOnSubClassNative", "()V", true, nullptr, 236 reinterpret_cast<void*>(trampoline_Java_Main_testCallStaticVoidMethodOnSubClassNative) }, 237 { "testFindClassOnAttachedNativeThread", "()V", true, nullptr, 238 reinterpret_cast<void*>(trampoline_Java_Main_testFindClassOnAttachedNativeThread) }, 239 { "testFindFieldOnAttachedNativeThreadNative", "()V", true, nullptr, 240 reinterpret_cast<void*>(trampoline_Java_Main_testFindFieldOnAttachedNativeThreadNative) }, 241 { "testGetMirandaMethodNative", "()Ljava/lang/reflect/Method;", true, nullptr, 242 reinterpret_cast<void*>(trampoline_Java_Main_testGetMirandaMethodNative) }, 243 { "testNewStringObject", "()V", true, nullptr, 244 reinterpret_cast<void*>(trampoline_Java_Main_testNewStringObject) }, 245 { "testZeroLengthByteBuffers", "()V", true, nullptr, 246 reinterpret_cast<void*>(trampoline_Java_Main_testZeroLengthByteBuffers) }, 247 { "testSignal", "()I", true, nullptr, 248 reinterpret_cast<void*>(trampoline_Java_Main_testSignal) }, 249 }; 250 251 static NativeBridgeMethod* find_native_bridge_method(const char *name) { 252 const char* pname = name; 253 if (strncmp(name, "Java_Main_", 10) == 0) { 254 pname += 10; 255 } 256 257 for (size_t i = 0; i < sizeof(gNativeBridgeMethods) / sizeof(gNativeBridgeMethods[0]); i++) { 258 if (strcmp(pname, gNativeBridgeMethods[i].name) == 0) { 259 return &gNativeBridgeMethods[i]; 260 } 261 } 262 return nullptr; 263 } 264 265 // NativeBridgeCallbacks implementations 266 extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* art_cbs, 267 const char* app_code_cache_dir, 268 const char* isa ATTRIBUTE_UNUSED) { 269 struct stat st; 270 if (app_code_cache_dir != nullptr) { 271 if (stat(app_code_cache_dir, &st) == 0) { 272 if (!S_ISDIR(st.st_mode)) { 273 printf("Code cache is not a directory.\n"); 274 } 275 } else { 276 perror("Error when stat-ing the code_cache:"); 277 } 278 } 279 280 if (art_cbs != nullptr) { 281 gNativeBridgeArtCallbacks = art_cbs; 282 printf("Native bridge initialized.\n"); 283 } 284 return true; 285 } 286 287 extern "C" void* native_bridge_loadLibrary(const char* libpath, int flag) { 288 size_t len = strlen(libpath); 289 char* tmp = new char[len + 10]; 290 strncpy(tmp, libpath, len); 291 tmp[len - 3] = '2'; 292 tmp[len - 2] = '.'; 293 tmp[len - 1] = 's'; 294 tmp[len] = 'o'; 295 tmp[len + 1] = 0; 296 void* handle = dlopen(tmp, flag); 297 delete[] tmp; 298 299 if (handle == nullptr) { 300 printf("Handle = nullptr!\n"); 301 printf("Was looking for %s.\n", libpath); 302 printf("Error = %s.\n", dlerror()); 303 char cwd[1024]; 304 if (getcwd(cwd, sizeof(cwd)) != nullptr) { 305 printf("Current working dir: %s\n", cwd); 306 } 307 } 308 return handle; 309 } 310 311 extern "C" void* native_bridge_getTrampoline(void* handle, const char* name, const char* shorty, 312 uint32_t len ATTRIBUTE_UNUSED) { 313 printf("Getting trampoline for %s with shorty %s.\n", name, shorty); 314 315 // The name here is actually the JNI name, so we can directly do the lookup. 316 void* sym = dlsym(handle, name); 317 NativeBridgeMethod* method = find_native_bridge_method(name); 318 if (method == nullptr) 319 return nullptr; 320 method->fnPtr = sym; 321 322 return method->trampoline; 323 } 324 325 extern "C" bool native_bridge_isSupported(const char* libpath) { 326 printf("Checking for support.\n"); 327 328 if (libpath == nullptr) { 329 return false; 330 } 331 // We don't want to hijack javacore. So we should get libarttest... 332 return strcmp(libpath, "libjavacore.so") != 0; 333 } 334 335 namespace android { 336 337 // Environment values required by the apps running with native bridge. 338 struct NativeBridgeRuntimeValues { 339 const char* os_arch; 340 const char* cpu_abi; 341 const char* cpu_abi2; 342 const char* *supported_abis; 343 int32_t abi_count; 344 }; 345 346 } // namespace android 347 348 const char* supported_abis[] = { 349 "supported1", "supported2", "supported3" 350 }; 351 352 const struct android::NativeBridgeRuntimeValues nb_env { 353 .os_arch = "os.arch", 354 .cpu_abi = "cpu_abi", 355 .cpu_abi2 = "cpu_abi2", 356 .supported_abis = supported_abis, 357 .abi_count = 3 358 }; 359 360 extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv( 361 const char* abi) { 362 printf("Checking for getEnvValues.\n"); 363 364 if (abi == nullptr) { 365 return nullptr; 366 } 367 368 return &nb_env; 369 } 370 371 // v2 parts. 372 373 extern "C" bool nb_is_compatible(uint32_t bridge_version ATTRIBUTE_UNUSED) { 374 return true; 375 } 376 377 #if defined(__i386__) || defined(__x86_64__) 378 #if defined(__APPLE__) 379 #define ucontext __darwin_ucontext 380 381 #if defined(__x86_64__) 382 // 64 bit mac build. 383 #define CTX_EIP uc_mcontext->__ss.__rip 384 #else 385 // 32 bit mac build. 386 #define CTX_EIP uc_mcontext->__ss.__eip 387 #endif 388 389 #elif defined(__x86_64__) 390 // 64 bit linux build. 391 #define CTX_EIP uc_mcontext.gregs[REG_RIP] 392 #else 393 // 32 bit linux build. 394 #define CTX_EIP uc_mcontext.gregs[REG_EIP] 395 #endif 396 #endif 397 398 static bool cannot_be_blocked(int signum) { 399 // These two sigs cannot be blocked anywhere. 400 if ((signum == SIGKILL) || (signum == SIGSTOP)) { 401 return true; 402 } 403 404 // The invalid rt_sig cannot be blocked. 405 if (((signum >= 32) && (signum < SIGRTMIN)) || (signum > SIGRTMAX)) { 406 return true; 407 } 408 409 return false; 410 } 411 412 // A dummy special handler, continueing after the faulting location. This code comes from 413 // 004-SignalTest. 414 static bool nb_signalhandler(int sig, siginfo_t* info ATTRIBUTE_UNUSED, void* context) { 415 printf("NB signal handler with signal %d.\n", sig); 416 if (sig == SIGSEGV) { 417 #if defined(__arm__) 418 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 419 struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext); 420 sc->arm_pc += 2; // Skip instruction causing segv & sigill. 421 #elif defined(__aarch64__) 422 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 423 struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext); 424 sc->pc += 4; // Skip instruction causing segv & sigill. 425 #elif defined(__i386__) 426 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 427 uc->CTX_EIP += 3; 428 #elif defined(__x86_64__) 429 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 430 uc->CTX_EIP += 2; 431 #else 432 UNUSED(context); 433 #endif 434 } 435 436 // Before invoking this handler, all other unclaimed signals must be blocked. 437 // We're trying to check the signal mask to verify its status here. 438 sigset_t tmpset; 439 sigemptyset(&tmpset); 440 sigprocmask(SIG_SETMASK, nullptr, &tmpset); 441 int other_claimed = (sig == SIGSEGV) ? SIGILL : SIGSEGV; 442 for (int signum = 0; signum < NSIG; ++signum) { 443 if (cannot_be_blocked(signum)) { 444 continue; 445 } else if ((sigismember(&tmpset, signum)) && (signum == other_claimed)) { 446 printf("ERROR: The claimed signal %d is blocked\n", signum); 447 } else if ((!sigismember(&tmpset, signum)) && (signum != other_claimed)) { 448 printf("ERROR: The unclaimed signal %d is not blocked\n", signum); 449 } 450 } 451 452 // We handled this... 453 return true; 454 } 455 456 static ::android::NativeBridgeSignalHandlerFn native_bridge_get_signal_handler(int signal) { 457 // Test segv for already claimed signal, and sigill for not claimed signal 458 if ((signal == SIGSEGV) || (signal == SIGILL)) { 459 return &nb_signalhandler; 460 } 461 return nullptr; 462 } 463 464 465 // "NativeBridgeItf" is effectively an API (it is the name of the symbol that will be loaded 466 // by the native bridge library). 467 android::NativeBridgeCallbacks NativeBridgeItf { 468 .version = 2, 469 .initialize = &native_bridge_initialize, 470 .loadLibrary = &native_bridge_loadLibrary, 471 .getTrampoline = &native_bridge_getTrampoline, 472 .isSupported = &native_bridge_isSupported, 473 .getAppEnv = &native_bridge_getAppEnv, 474 .isCompatibleWith = &nb_is_compatible, 475 .getSignalHandler = &native_bridge_get_signal_handler 476 }; 477