Home | History | Annotate | Download | only in 115-native-bridge
      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