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