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