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 35 struct NativeBridgeMethod { 36 const char* name; 37 const char* signature; 38 bool static_method; 39 void* fnPtr; 40 void* trampoline; 41 }; 42 43 static NativeBridgeMethod* find_native_bridge_method(const char *name); 44 static const android::NativeBridgeRuntimeCallbacks* gNativeBridgeArtCallbacks; 45 46 static 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 94 static 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 103 static 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 112 static 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 121 static 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 129 static 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 137 static 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 145 static 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 155 static 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 165 static 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 176 static 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. 187 char *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 196 static 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 209 static 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. 250 enum class TestStatus { 251 kNone, 252 kRaiseFirst, 253 kHandleFirst, 254 kRaiseSecond, 255 kHandleSecond, 256 }; 257 258 // State transition helper for testSignalHandlerNotReturn. 259 class 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 312 static SignalHandlerTestStatus gSignalTestStatus; 313 // The context is used to jump out from signal handler. 314 static 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. 328 static 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. 352 static 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 375 NativeBridgeMethod 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 404 static 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 419 extern "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 440 extern "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 468 extern "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 482 extern "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 492 namespace android { 493 494 // Environment values required by the apps running with native bridge. 495 struct 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 505 const char* supported_abis[] = { 506 "supported1", "supported2", "supported3" 507 }; 508 509 const 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 517 extern "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 530 extern "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 555 static 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. 583 static 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 596 static ::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 604 extern "C" int native_bridge_unloadLibrary(void* handle ATTRIBUTE_UNUSED) { 605 printf("dlclose() in native bridge.\n"); 606 return 0; 607 } 608 609 extern "C" const char* native_bridge_getError() { 610 printf("getError() in native bridge.\n"); 611 return ""; 612 } 613 614 extern "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 619 extern "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 625 extern "C" android::native_bridge_namespace_t* 626 native_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 636 extern "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 643 extern "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). 652 android::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