Home | History | Annotate | Download | only in runtime
      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 #include "native_bridge_art_interface.h"
     18 
     19 #include <signal.h>
     20 
     21 #include "nativebridge/native_bridge.h"
     22 
     23 #include "art_method-inl.h"
     24 #include "base/enums.h"
     25 #include "base/logging.h"  // For VLOG.
     26 #include "base/macros.h"
     27 #include "dex/dex_file-inl.h"
     28 #include "jni_internal.h"
     29 #include "mirror/class-inl.h"
     30 #include "scoped_thread_state_change-inl.h"
     31 #include "sigchain.h"
     32 
     33 namespace art {
     34 
     35 static const char* GetMethodShorty(JNIEnv* env, jmethodID mid) {
     36   ScopedObjectAccess soa(env);
     37   ArtMethod* m = jni::DecodeArtMethod(mid);
     38   return m->GetShorty();
     39 }
     40 
     41 static uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz) {
     42   if (clazz == nullptr) {
     43     return 0;
     44   }
     45 
     46   ScopedObjectAccess soa(env);
     47   ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(clazz);
     48 
     49   uint32_t native_method_count = 0;
     50   for (auto& m : c->GetMethods(kRuntimePointerSize)) {
     51     native_method_count += m.IsNative() ? 1u : 0u;
     52   }
     53   return native_method_count;
     54 }
     55 
     56 static uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
     57                                  uint32_t method_count) {
     58   if ((clazz == nullptr) || (methods == nullptr)) {
     59     return 0;
     60   }
     61   ScopedObjectAccess soa(env);
     62   ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(clazz);
     63 
     64   uint32_t count = 0;
     65   for (auto& m : c->GetMethods(kRuntimePointerSize)) {
     66     if (m.IsNative()) {
     67       if (count < method_count) {
     68         methods[count].name = m.GetName();
     69         methods[count].signature = m.GetShorty();
     70         methods[count].fnPtr = m.GetEntryPointFromJni();
     71         count++;
     72       } else {
     73         LOG(WARNING) << "Output native method array too small. Skipping "
     74                      << m.PrettyMethod();
     75       }
     76     }
     77   }
     78   return count;
     79 }
     80 
     81 // Native bridge library runtime callbacks. They represent the runtime interface to native bridge.
     82 //
     83 // The interface is expected to expose the following methods:
     84 // getMethodShorty(): in the case of native method calling JNI native function CallXXXXMethodY(),
     85 //   native bridge calls back to VM for the shorty of the method so that it can prepare based on
     86 //   host calling convention.
     87 // getNativeMethodCount() and getNativeMethods(): in case of JNI function UnregisterNatives(),
     88 //   native bridge can call back to get all native methods of specified class so that all
     89 //   corresponding trampolines can be destroyed.
     90 static android::NativeBridgeRuntimeCallbacks native_bridge_art_callbacks_ {
     91   GetMethodShorty, GetNativeMethodCount, GetNativeMethods
     92 };
     93 
     94 bool LoadNativeBridge(const std::string& native_bridge_library_filename) {
     95   VLOG(startup) << "Runtime::Setup native bridge library: "
     96       << (native_bridge_library_filename.empty() ? "(empty)" : native_bridge_library_filename);
     97   return android::LoadNativeBridge(native_bridge_library_filename.c_str(),
     98                                    &native_bridge_art_callbacks_);
     99 }
    100 
    101 void PreInitializeNativeBridge(const std::string& dir) {
    102   VLOG(startup) << "Runtime::Pre-initialize native bridge";
    103 #ifndef __APPLE__  // Mac OS does not support CLONE_NEWNS.
    104   if (unshare(CLONE_NEWNS) == -1) {
    105     LOG(WARNING) << "Could not create mount namespace.";
    106   }
    107   android::PreInitializeNativeBridge(dir.c_str(), GetInstructionSetString(kRuntimeISA));
    108 #else
    109   UNUSED(dir);
    110 #endif
    111 }
    112 
    113 void InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
    114   if (android::InitializeNativeBridge(env, instruction_set)) {
    115     if (android::NativeBridgeGetVersion() >= 2U) {
    116 #ifdef _NSIG  // Undefined on Apple, but we don't support running on Mac, anyways.
    117       // Managed signal handling support added in version 2.
    118       for (int signal = 0; signal < _NSIG; ++signal) {
    119         android::NativeBridgeSignalHandlerFn fn = android::NativeBridgeGetSignalHandler(signal);
    120         if (fn != nullptr) {
    121           sigset_t mask;
    122           sigfillset(&mask);
    123           SigchainAction sa = {
    124             .sc_sigaction = fn,
    125             .sc_mask = mask,
    126             // The native bridge signal might not return back to sigchain's handler.
    127             .sc_flags = SIGCHAIN_ALLOW_NORETURN,
    128           };
    129           AddSpecialSignalHandlerFn(signal, &sa);
    130         }
    131       }
    132 #endif
    133     }
    134   }
    135 }
    136 
    137 void UnloadNativeBridge() {
    138   android::UnloadNativeBridge();
    139 }
    140 
    141 }  // namespace art
    142