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 <dlfcn.h> 20#include <setjmp.h> 21#include <signal.h> 22#include <sys/stat.h> 23#include <unistd.h> 24 25#include <algorithm> 26#include <cstdio> 27#include <cstdlib> 28#include <vector> 29 30#include <jni.h> 31#include <nativebridge/native_bridge.h> 32 33#include "base/macros.h" 34 35struct NativeBridgeMethod { 36 const char* name; 37 const char* signature; 38 bool static_method; 39 void* fnPtr; 40 void* trampoline; 41}; 42 43static NativeBridgeMethod* find_native_bridge_method(const char *name); 44static const android::NativeBridgeRuntimeCallbacks* gNativeBridgeArtCallbacks; 45 46static jint trampoline_JNI_OnLoad(JavaVM* vm, void* reserved) { 47 JNIEnv* env = nullptr; 48 typedef jint (*FnPtr_t)(JavaVM*, void*); 49 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("JNI_OnLoad")->fnPtr); 50 51 vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6); 52 if (env == nullptr) { 53 return 0; 54 } 55 56 jclass klass = env->FindClass("Main"); 57 if (klass != nullptr) { 58 int i, count1, count2; 59 count1 = gNativeBridgeArtCallbacks->getNativeMethodCount(env, klass); 60 std::unique_ptr<JNINativeMethod[]> methods(new JNINativeMethod[count1]); 61 if (methods == nullptr) { 62 return 0; 63 } 64 count2 = gNativeBridgeArtCallbacks->getNativeMethods(env, klass, methods.get(), count1); 65 if (count1 == count2) { 66 printf("Test ART callbacks: all JNI function number is %d.\n", count1); 67 } 68 69 for (i = 0; i < count1; i++) { 70 NativeBridgeMethod* nb_method = find_native_bridge_method(methods[i].name); 71 if (nb_method != nullptr) { 72 jmethodID mid = nullptr; 73 if (nb_method->static_method) { 74 mid = env->GetStaticMethodID(klass, methods[i].name, nb_method->signature); 75 } else { 76 mid = env->GetMethodID(klass, methods[i].name, nb_method->signature); 77 } 78 if (mid != nullptr) { 79 const char* shorty = gNativeBridgeArtCallbacks->getMethodShorty(env, mid); 80 if (strcmp(shorty, methods[i].signature) == 0) { 81 printf(" name:%s, signature:%s, shorty:%s.\n", 82 methods[i].name, nb_method->signature, shorty); 83 } 84 } 85 } 86 } 87 methods.release(); 88 } 89 90 printf("%s called!\n", __FUNCTION__); 91 return fnPtr(vm, reserved); 92} 93 94static void trampoline_Java_Main_testFindClassOnAttachedNativeThread(JNIEnv* env, 95 jclass klass) { 96 typedef void (*FnPtr_t)(JNIEnv*, jclass); 97 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 98 (find_native_bridge_method("testFindClassOnAttachedNativeThread")->fnPtr); 99 printf("%s called!\n", __FUNCTION__); 100 return fnPtr(env, klass); 101} 102 103static void trampoline_Java_Main_testFindFieldOnAttachedNativeThreadNative(JNIEnv* env, 104 jclass klass) { 105 typedef void (*FnPtr_t)(JNIEnv*, jclass); 106 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 107 (find_native_bridge_method("testFindFieldOnAttachedNativeThreadNative")->fnPtr); 108 printf("%s called!\n", __FUNCTION__); 109 return fnPtr(env, klass); 110} 111 112static void trampoline_Java_Main_testCallStaticVoidMethodOnSubClassNative(JNIEnv* env, 113 jclass klass) { 114 typedef void (*FnPtr_t)(JNIEnv*, jclass); 115 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 116 (find_native_bridge_method("testCallStaticVoidMethodOnSubClassNative")->fnPtr); 117 printf("%s called!\n", __FUNCTION__); 118 return fnPtr(env, klass); 119} 120 121static jobject trampoline_Java_Main_testGetMirandaMethodNative(JNIEnv* env, jclass klass) { 122 typedef jobject (*FnPtr_t)(JNIEnv*, jclass); 123 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 124 (find_native_bridge_method("testGetMirandaMethodNative")->fnPtr); 125 printf("%s called!\n", __FUNCTION__); 126 return fnPtr(env, klass); 127} 128 129static void trampoline_Java_Main_testNewStringObject(JNIEnv* env, jclass klass) { 130 typedef void (*FnPtr_t)(JNIEnv*, jclass); 131 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 132 (find_native_bridge_method("testNewStringObject")->fnPtr); 133 printf("%s called!\n", __FUNCTION__); 134 return fnPtr(env, klass); 135} 136 137static void trampoline_Java_Main_testZeroLengthByteBuffers(JNIEnv* env, jclass klass) { 138 typedef void (*FnPtr_t)(JNIEnv*, jclass); 139 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t> 140 (find_native_bridge_method("testZeroLengthByteBuffers")->fnPtr); 141 printf("%s called!\n", __FUNCTION__); 142 return fnPtr(env, klass); 143} 144 145static jbyte trampoline_Java_Main_byteMethod(JNIEnv* env, jclass klass, jbyte b1, jbyte b2, 146 jbyte b3, jbyte b4, jbyte b5, jbyte b6, 147 jbyte b7, jbyte b8, jbyte b9, jbyte b10) { 148 typedef jbyte (*FnPtr_t)(JNIEnv*, jclass, jbyte, jbyte, jbyte, jbyte, jbyte, 149 jbyte, jbyte, jbyte, jbyte, jbyte); 150 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("byteMethod")->fnPtr); 151 printf("%s called!\n", __FUNCTION__); 152 return fnPtr(env, klass, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10); 153} 154 155static jshort trampoline_Java_Main_shortMethod(JNIEnv* env, jclass klass, jshort s1, jshort s2, 156 jshort s3, jshort s4, jshort s5, jshort s6, 157 jshort s7, jshort s8, jshort s9, jshort s10) { 158 typedef jshort (*FnPtr_t)(JNIEnv*, jclass, jshort, jshort, jshort, jshort, jshort, 159 jshort, jshort, jshort, jshort, jshort); 160 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("shortMethod")->fnPtr); 161 printf("%s called!\n", __FUNCTION__); 162 return fnPtr(env, klass, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10); 163} 164 165static jboolean trampoline_Java_Main_booleanMethod(JNIEnv* env, jclass klass, jboolean b1, 166 jboolean b2, jboolean b3, jboolean b4, 167 jboolean b5, jboolean b6, jboolean b7, 168 jboolean b8, jboolean b9, jboolean b10) { 169 typedef jboolean (*FnPtr_t)(JNIEnv*, jclass, jboolean, jboolean, jboolean, jboolean, jboolean, 170 jboolean, jboolean, jboolean, jboolean, jboolean); 171 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("booleanMethod")->fnPtr); 172 printf("%s called!\n", __FUNCTION__); 173 return fnPtr(env, klass, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10); 174} 175 176static jchar trampoline_Java_Main_charMethod(JNIEnv* env, jclass klass, jchar c1, jchar c2, 177 jchar c3, jchar c4, jchar c5, jchar c6, 178 jchar c7, jchar c8, jchar c9, jchar c10) { 179 typedef jchar (*FnPtr_t)(JNIEnv*, jclass, jchar, jchar, jchar, jchar, jchar, 180 jchar, jchar, jchar, jchar, jchar); 181 FnPtr_t fnPtr = reinterpret_cast<FnPtr_t>(find_native_bridge_method("charMethod")->fnPtr); 182 printf("%s called!\n", __FUNCTION__); 183 return fnPtr(env, klass, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10); 184} 185 186// This code is adapted from 004-SignalTest and causes a segfault. 187char *go_away_compiler = nullptr; 188 189[[ noreturn ]] static void test_sigaction_handler(int sig ATTRIBUTE_UNUSED, 190 siginfo_t* info ATTRIBUTE_UNUSED, 191 void* context ATTRIBUTE_UNUSED) { 192 printf("Should not reach the test sigaction handler."); 193 abort(); 194} 195 196static void raise_sigsegv() { 197#if defined(__arm__) || defined(__i386__) || defined(__aarch64__) 198 *go_away_compiler = 'a'; 199#elif defined(__x86_64__) 200 // Cause a SEGV using an instruction known to be 2 bytes long to account for hardcoded jump 201 // in the signal handler 202 asm volatile("movl $0, %%eax;" "movb %%ah, (%%rax);" : : : "%eax"); 203#else 204 // On other architectures we simulate SEGV. 205 kill(getpid(), SIGSEGV); 206#endif 207} 208 209static jint trampoline_Java_Main_testSignal(JNIEnv*, jclass) { 210 // Install the sigaction handler above, which should *not* be reached as the native-bridge 211 // handler should be called first. Note: we won't chain at all, if we ever get here, we'll die. 212 struct sigaction tmp; 213 sigemptyset(&tmp.sa_mask); 214 tmp.sa_sigaction = test_sigaction_handler; 215#if !defined(__APPLE__) && !defined(__mips__) 216 tmp.sa_restorer = nullptr; 217#endif 218 219 // Test segv 220 sigaction(SIGSEGV, &tmp, nullptr); 221 raise_sigsegv(); 222 223 // Test sigill 224 sigaction(SIGILL, &tmp, nullptr); 225 kill(getpid(), SIGILL); 226 227#if defined(__BIONIC__) 228 // Do the same again, but with sigaction64. 229 struct sigaction64 tmp2; 230 sigemptyset64(&tmp2.sa_mask); 231 tmp2.sa_sigaction = test_sigaction_handler; 232 tmp2.sa_restorer = nullptr; 233 234 sigaction64(SIGSEGV, &tmp2, nullptr); 235 sigaction64(SIGILL, &tmp2, nullptr); 236#endif 237 238 // Reraise SIGSEGV/SIGILL even on non-bionic, so that the expected output is 239 // the same. 240 raise_sigsegv(); 241 kill(getpid(), SIGILL); 242 243 return 1234; 244} 245 246// Status of the tricky control path of testSignalHandlerNotReturn. 247// 248// "kNone" is the default status except testSignalHandlerNotReturn, 249// others are used by testSignalHandlerNotReturn. 250enum class TestStatus { 251 kNone, 252 kRaiseFirst, 253 kHandleFirst, 254 kRaiseSecond, 255 kHandleSecond, 256}; 257 258// State transition helper for testSignalHandlerNotReturn. 259class SignalHandlerTestStatus { 260 public: 261 SignalHandlerTestStatus() : state_(TestStatus::kNone) { 262 } 263 264 TestStatus Get() { 265 return state_; 266 } 267 268 void Reset() { 269 Set(TestStatus::kNone); 270 } 271 272 void Set(TestStatus state) { 273 switch (state) { 274 case TestStatus::kNone: 275 AssertState(TestStatus::kHandleSecond); 276 break; 277 278 case TestStatus::kRaiseFirst: 279 AssertState(TestStatus::kNone); 280 break; 281 282 case TestStatus::kHandleFirst: 283 AssertState(TestStatus::kRaiseFirst); 284 break; 285 286 case TestStatus::kRaiseSecond: 287 AssertState(TestStatus::kHandleFirst); 288 break; 289 290 case TestStatus::kHandleSecond: 291 AssertState(TestStatus::kRaiseSecond); 292 break; 293 294 default: 295 printf("ERROR: unknown state\n"); 296 abort(); 297 } 298 299 state_ = state; 300 } 301 302 private: 303 TestStatus state_; 304 305 void AssertState(TestStatus expected) { 306 if (state_ != expected) { 307 printf("ERROR: unexpected state, was %d, expected %d\n", state_, expected); 308 } 309 } 310}; 311 312static SignalHandlerTestStatus gSignalTestStatus; 313// The context is used to jump out from signal handler. 314static sigjmp_buf gSignalTestJmpBuf; 315 316// Test whether NativeBridge can receive future signal when its handler doesn't return. 317// 318// Control path: 319// 1. Raise first SIGSEGV in test function. 320// 2. Raise another SIGSEGV in NativeBridge's signal handler which is handling 321// the first SIGSEGV. 322// 3. Expect that NativeBridge's signal handler invokes again. And jump back 323// to test function in when handling second SIGSEGV. 324// 4. Exit test. 325// 326// NOTE: sigchain should be aware that "special signal handler" may not return. 327// Pay attention if this case fails. 328static void trampoline_Java_Main_testSignalHandlerNotReturn(JNIEnv*, jclass) { 329 if (gSignalTestStatus.Get() != TestStatus::kNone) { 330 printf("ERROR: test already started?\n"); 331 return; 332 } 333 printf("start testSignalHandlerNotReturn\n"); 334 335 if (sigsetjmp(gSignalTestJmpBuf, 1) == 0) { 336 gSignalTestStatus.Set(TestStatus::kRaiseFirst); 337 printf("raising first SIGSEGV\n"); 338 raise_sigsegv(); 339 } else { 340 // jump to here from signal handler when handling second SIGSEGV. 341 if (gSignalTestStatus.Get() != TestStatus::kHandleSecond) { 342 printf("ERROR: not jump from second SIGSEGV?\n"); 343 return; 344 } 345 gSignalTestStatus.Reset(); 346 printf("back to test from signal handler via siglongjmp(), and done!\n"); 347 } 348} 349 350// Signal handler for testSignalHandlerNotReturn. 351// This handler won't return. 352static bool NotReturnSignalHandler() { 353 if (gSignalTestStatus.Get() == TestStatus::kRaiseFirst) { 354 // handling first SIGSEGV 355 gSignalTestStatus.Set(TestStatus::kHandleFirst); 356 printf("handling first SIGSEGV, will raise another\n"); 357 sigset_t set; 358 sigemptyset(&set); 359 sigaddset(&set, SIGSEGV); 360 printf("unblock SIGSEGV in handler\n"); 361 sigprocmask(SIG_UNBLOCK, &set, nullptr); 362 gSignalTestStatus.Set(TestStatus::kRaiseSecond); 363 printf("raising second SIGSEGV\n"); 364 raise_sigsegv(); // raise second SIGSEGV 365 } else if (gSignalTestStatus.Get() == TestStatus::kRaiseSecond) { 366 // handling second SIGSEGV 367 gSignalTestStatus.Set(TestStatus::kHandleSecond); 368 printf("handling second SIGSEGV, will jump back to test function\n"); 369 siglongjmp(gSignalTestJmpBuf, 1); 370 } 371 printf("ERROR: should not reach here!\n"); 372 return false; 373} 374 375NativeBridgeMethod gNativeBridgeMethods[] = { 376 { "JNI_OnLoad", "", true, nullptr, 377 reinterpret_cast<void*>(trampoline_JNI_OnLoad) }, 378 { "booleanMethod", "(ZZZZZZZZZZ)Z", true, nullptr, 379 reinterpret_cast<void*>(trampoline_Java_Main_booleanMethod) }, 380 { "byteMethod", "(BBBBBBBBBB)B", true, nullptr, 381 reinterpret_cast<void*>(trampoline_Java_Main_byteMethod) }, 382 { "charMethod", "(CCCCCCCCCC)C", true, nullptr, 383 reinterpret_cast<void*>(trampoline_Java_Main_charMethod) }, 384 { "shortMethod", "(SSSSSSSSSS)S", true, nullptr, 385 reinterpret_cast<void*>(trampoline_Java_Main_shortMethod) }, 386 { "testCallStaticVoidMethodOnSubClassNative", "()V", true, nullptr, 387 reinterpret_cast<void*>(trampoline_Java_Main_testCallStaticVoidMethodOnSubClassNative) }, 388 { "testFindClassOnAttachedNativeThread", "()V", true, nullptr, 389 reinterpret_cast<void*>(trampoline_Java_Main_testFindClassOnAttachedNativeThread) }, 390 { "testFindFieldOnAttachedNativeThreadNative", "()V", true, nullptr, 391 reinterpret_cast<void*>(trampoline_Java_Main_testFindFieldOnAttachedNativeThreadNative) }, 392 { "testGetMirandaMethodNative", "()Ljava/lang/reflect/Method;", true, nullptr, 393 reinterpret_cast<void*>(trampoline_Java_Main_testGetMirandaMethodNative) }, 394 { "testNewStringObject", "()V", true, nullptr, 395 reinterpret_cast<void*>(trampoline_Java_Main_testNewStringObject) }, 396 { "testZeroLengthByteBuffers", "()V", true, nullptr, 397 reinterpret_cast<void*>(trampoline_Java_Main_testZeroLengthByteBuffers) }, 398 { "testSignal", "()I", true, nullptr, 399 reinterpret_cast<void*>(trampoline_Java_Main_testSignal) }, 400 { "testSignalHandlerNotReturn", "()V", true, nullptr, 401 reinterpret_cast<void*>(trampoline_Java_Main_testSignalHandlerNotReturn) }, 402}; 403 404static NativeBridgeMethod* find_native_bridge_method(const char *name) { 405 const char* pname = name; 406 if (strncmp(name, "Java_Main_", 10) == 0) { 407 pname += 10; 408 } 409 410 for (size_t i = 0; i < sizeof(gNativeBridgeMethods) / sizeof(gNativeBridgeMethods[0]); i++) { 411 if (strcmp(pname, gNativeBridgeMethods[i].name) == 0) { 412 return &gNativeBridgeMethods[i]; 413 } 414 } 415 return nullptr; 416} 417 418// NativeBridgeCallbacks implementations 419extern "C" bool native_bridge_initialize(const android::NativeBridgeRuntimeCallbacks* art_cbs, 420 const char* app_code_cache_dir, 421 const char* isa ATTRIBUTE_UNUSED) { 422 struct stat st; 423 if (app_code_cache_dir != nullptr) { 424 if (stat(app_code_cache_dir, &st) == 0) { 425 if (!S_ISDIR(st.st_mode)) { 426 printf("Code cache is not a directory.\n"); 427 } 428 } else { 429 perror("Error when stat-ing the code_cache:"); 430 } 431 } 432 433 if (art_cbs != nullptr) { 434 gNativeBridgeArtCallbacks = art_cbs; 435 printf("Native bridge initialized.\n"); 436 } 437 return true; 438} 439 440extern "C" void* native_bridge_loadLibrary(const char* libpath, int flag) { 441 if (strstr(libpath, "libinvalid.so") != nullptr) { 442 printf("Was to load 'libinvalid.so', force fail.\n"); 443 return nullptr; 444 } 445 size_t len = strlen(libpath); 446 char* tmp = new char[len + 10]; 447 strncpy(tmp, libpath, len); 448 tmp[len - 3] = '2'; 449 tmp[len - 2] = '.'; 450 tmp[len - 1] = 's'; 451 tmp[len] = 'o'; 452 tmp[len + 1] = 0; 453 void* handle = dlopen(tmp, flag); 454 delete[] tmp; 455 456 if (handle == nullptr) { 457 printf("Handle = nullptr!\n"); 458 printf("Was looking for %s.\n", libpath); 459 printf("Error = %s.\n", dlerror()); 460 char cwd[1024] = {'\0'}; 461 if (getcwd(cwd, sizeof(cwd)) != nullptr) { 462 printf("Current working dir: %s\n", cwd); 463 } 464 } 465 return handle; 466} 467 468extern "C" void* native_bridge_getTrampoline(void* handle, const char* name, const char* shorty, 469 uint32_t len ATTRIBUTE_UNUSED) { 470 printf("Getting trampoline for %s with shorty %s.\n", name, shorty); 471 472 // The name here is actually the JNI name, so we can directly do the lookup. 473 void* sym = dlsym(handle, name); 474 NativeBridgeMethod* method = find_native_bridge_method(name); 475 if (method == nullptr) 476 return nullptr; 477 method->fnPtr = sym; 478 479 return method->trampoline; 480} 481 482extern "C" bool native_bridge_isSupported(const char* libpath) { 483 printf("Checking for support.\n"); 484 485 if (libpath == nullptr) { 486 return false; 487 } 488 // We don't want to hijack javacore. So we should get libarttest... 489 return strcmp(libpath, "libjavacore.so") != 0; 490} 491 492namespace android { 493 494// Environment values required by the apps running with native bridge. 495struct NativeBridgeRuntimeValues { 496 const char* os_arch; 497 const char* cpu_abi; 498 const char* cpu_abi2; 499 const char* *supported_abis; 500 int32_t abi_count; 501}; 502 503} // namespace android 504 505const char* supported_abis[] = { 506 "supported1", "supported2", "supported3" 507}; 508 509const struct android::NativeBridgeRuntimeValues nb_env { 510 .os_arch = "os.arch", 511 .cpu_abi = "cpu_abi", 512 .cpu_abi2 = "cpu_abi2", 513 .supported_abis = supported_abis, 514 .abi_count = 3 515}; 516 517extern "C" const struct android::NativeBridgeRuntimeValues* native_bridge_getAppEnv( 518 const char* abi) { 519 printf("Checking for getEnvValues.\n"); 520 521 if (abi == nullptr) { 522 return nullptr; 523 } 524 525 return &nb_env; 526} 527 528// v2 parts. 529 530extern "C" bool native_bridge_isCompatibleWith(uint32_t bridge_version ATTRIBUTE_UNUSED) { 531 return true; 532} 533 534#if defined(__i386__) || defined(__x86_64__) 535#if defined(__APPLE__) 536#define ucontext __darwin_ucontext 537 538#if defined(__x86_64__) 539// 64 bit mac build. 540#define CTX_EIP uc_mcontext->__ss.__rip 541#else 542// 32 bit mac build. 543#define CTX_EIP uc_mcontext->__ss.__eip 544#endif 545 546#elif defined(__x86_64__) 547// 64 bit linux build. 548#define CTX_EIP uc_mcontext.gregs[REG_RIP] 549#else 550// 32 bit linux build. 551#define CTX_EIP uc_mcontext.gregs[REG_EIP] 552#endif 553#endif 554 555static bool StandardSignalHandler(int sig, siginfo_t* info ATTRIBUTE_UNUSED, 556 void* context) { 557 if (sig == SIGSEGV) { 558#if defined(__arm__) 559 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 560 struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext); 561 sc->arm_pc += 2; // Skip instruction causing segv & sigill. 562#elif defined(__aarch64__) 563 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 564 struct sigcontext *sc = reinterpret_cast<struct sigcontext*>(&uc->uc_mcontext); 565 sc->pc += 4; // Skip instruction causing segv & sigill. 566#elif defined(__i386__) 567 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 568 uc->CTX_EIP += 3; 569#elif defined(__x86_64__) 570 struct ucontext *uc = reinterpret_cast<struct ucontext*>(context); 571 uc->CTX_EIP += 2; 572#else 573 UNUSED(context); 574#endif 575 } 576 577 // We handled this... 578 return true; 579} 580 581// A dummy special handler, continueing after the faulting location. This code comes from 582// 004-SignalTest. 583static bool nb_signalhandler(int sig, siginfo_t* info, void* context) { 584 printf("NB signal handler with signal %d.\n", sig); 585 586 if (gSignalTestStatus.Get() == TestStatus::kNone) { 587 return StandardSignalHandler(sig, info, context); 588 } else if (sig == SIGSEGV) { 589 return NotReturnSignalHandler(); 590 } else { 591 printf("ERROR: should not reach here!\n"); 592 return false; 593 } 594} 595 596static ::android::NativeBridgeSignalHandlerFn native_bridge_getSignalHandler(int signal) { 597 // Test segv for already claimed signal, and sigill for not claimed signal 598 if ((signal == SIGSEGV) || (signal == SIGILL)) { 599 return &nb_signalhandler; 600 } 601 return nullptr; 602} 603 604extern "C" int native_bridge_unloadLibrary(void* handle ATTRIBUTE_UNUSED) { 605 printf("dlclose() in native bridge.\n"); 606 return 0; 607} 608 609extern "C" const char* native_bridge_getError() { 610 printf("getError() in native bridge.\n"); 611 return ""; 612} 613 614extern "C" bool native_bridge_isPathSupported(const char* library_path ATTRIBUTE_UNUSED) { 615 printf("Checking for path support in native bridge.\n"); 616 return false; 617} 618 619extern "C" bool native_bridge_initAnonymousNamespace(const char* public_ns_sonames ATTRIBUTE_UNUSED, 620 const char* anon_ns_library_path ATTRIBUTE_UNUSED) { 621 printf("Initializing anonymous namespace in native bridge.\n"); 622 return false; 623} 624 625extern "C" android::native_bridge_namespace_t* 626native_bridge_createNamespace(const char* name ATTRIBUTE_UNUSED, 627 const char* ld_library_path ATTRIBUTE_UNUSED, 628 const char* default_library_path ATTRIBUTE_UNUSED, 629 uint64_t type ATTRIBUTE_UNUSED, 630 const char* permitted_when_isolated_path ATTRIBUTE_UNUSED, 631 android::native_bridge_namespace_t* parent_ns ATTRIBUTE_UNUSED) { 632 printf("Creating namespace in native bridge.\n"); 633 return nullptr; 634} 635 636extern "C" bool native_bridge_linkNamespaces(android::native_bridge_namespace_t* from ATTRIBUTE_UNUSED, 637 android::native_bridge_namespace_t* to ATTRIBUTE_UNUSED, 638 const char* shared_libs_sonames ATTRIBUTE_UNUSED) { 639 printf("Linking namespaces in native bridge.\n"); 640 return false; 641} 642 643extern "C" void* native_bridge_loadLibraryExt(const char* libpath ATTRIBUTE_UNUSED, 644 int flag ATTRIBUTE_UNUSED, 645 android::native_bridge_namespace_t* ns ATTRIBUTE_UNUSED) { 646 printf("Loading library with Extension in native bridge.\n"); 647 return nullptr; 648} 649 650// "NativeBridgeItf" is effectively an API (it is the name of the symbol that will be loaded 651// by the native bridge library). 652android::NativeBridgeCallbacks NativeBridgeItf { 653 // v1 654 .version = 3, 655 .initialize = &native_bridge_initialize, 656 .loadLibrary = &native_bridge_loadLibrary, 657 .getTrampoline = &native_bridge_getTrampoline, 658 .isSupported = &native_bridge_isSupported, 659 .getAppEnv = &native_bridge_getAppEnv, 660 // v2 661 .isCompatibleWith = &native_bridge_isCompatibleWith, 662 .getSignalHandler = &native_bridge_getSignalHandler, 663 // v3 664 .unloadLibrary = &native_bridge_unloadLibrary, 665 .getError = &native_bridge_getError, 666 .isPathSupported = &native_bridge_isPathSupported, 667 .initAnonymousNamespace = &native_bridge_initAnonymousNamespace, 668 .createNamespace = &native_bridge_createNamespace, 669 .linkNamespaces = &native_bridge_linkNamespaces, 670 .loadLibraryExt = &native_bridge_loadLibraryExt 671}; 672