1 /* 2 * Copyright (C) 2008 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 <stdlib.h> 18 19 #include "debugger.h" 20 #include "instruction_set.h" 21 #include "jni_internal.h" 22 #include "JNIHelp.h" 23 #include "ScopedUtfChars.h" 24 #include "thread-inl.h" 25 26 #if defined(HAVE_PRCTL) 27 #include <sys/prctl.h> 28 #endif 29 30 #include <sys/resource.h> 31 32 namespace art { 33 34 static void EnableDebugger() { 35 // To let a non-privileged gdbserver attach to this 36 // process, we must set our dumpable flag. 37 #if defined(HAVE_PRCTL) 38 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) == -1) { 39 PLOG(ERROR) << "prctl(PR_SET_DUMPABLE) failed for pid " << getpid(); 40 } 41 #endif 42 // We don't want core dumps, though, so set the core dump size to 0. 43 rlimit rl; 44 rl.rlim_cur = 0; 45 rl.rlim_max = RLIM_INFINITY; 46 if (setrlimit(RLIMIT_CORE, &rl) == -1) { 47 PLOG(ERROR) << "setrlimit(RLIMIT_CORE) failed for pid " << getpid(); 48 } 49 } 50 51 static void EnableDebugFeatures(uint32_t debug_flags) { 52 // Must match values in dalvik.system.Zygote. 53 enum { 54 DEBUG_ENABLE_DEBUGGER = 1, 55 DEBUG_ENABLE_CHECKJNI = 1 << 1, 56 DEBUG_ENABLE_ASSERT = 1 << 2, 57 DEBUG_ENABLE_SAFEMODE = 1 << 3, 58 DEBUG_ENABLE_JNI_LOGGING = 1 << 4, 59 }; 60 61 if ((debug_flags & DEBUG_ENABLE_CHECKJNI) != 0) { 62 Runtime* runtime = Runtime::Current(); 63 JavaVMExt* vm = runtime->GetJavaVM(); 64 if (!vm->check_jni) { 65 LOG(INFO) << "Late-enabling -Xcheck:jni"; 66 vm->SetCheckJniEnabled(true); 67 // There's only one thread running at this point, so only one JNIEnv to fix up. 68 Thread::Current()->GetJniEnv()->SetCheckJniEnabled(true); 69 } else { 70 LOG(INFO) << "Not late-enabling -Xcheck:jni (already on)"; 71 } 72 debug_flags &= ~DEBUG_ENABLE_CHECKJNI; 73 } 74 75 if ((debug_flags & DEBUG_ENABLE_JNI_LOGGING) != 0) { 76 gLogVerbosity.third_party_jni = true; 77 debug_flags &= ~DEBUG_ENABLE_JNI_LOGGING; 78 } 79 80 Dbg::SetJdwpAllowed((debug_flags & DEBUG_ENABLE_DEBUGGER) != 0); 81 if ((debug_flags & DEBUG_ENABLE_DEBUGGER) != 0) { 82 EnableDebugger(); 83 } 84 debug_flags &= ~DEBUG_ENABLE_DEBUGGER; 85 86 if ((debug_flags & DEBUG_ENABLE_SAFEMODE) != 0) { 87 // Ensure that any (secondary) oat files will be interpreted. 88 Runtime* runtime = Runtime::Current(); 89 runtime->AddCompilerOption("--compiler-filter=interpret-only"); 90 debug_flags &= ~DEBUG_ENABLE_SAFEMODE; 91 } 92 93 // This is for backwards compatibility with Dalvik. 94 debug_flags &= ~DEBUG_ENABLE_ASSERT; 95 96 if (debug_flags != 0) { 97 LOG(ERROR) << StringPrintf("Unknown bits set in debug_flags: %#x", debug_flags); 98 } 99 } 100 101 static jlong ZygoteHooks_nativePreFork(JNIEnv* env, jclass) { 102 Runtime* runtime = Runtime::Current(); 103 CHECK(runtime->IsZygote()) << "runtime instance not started with -Xzygote"; 104 105 runtime->PreZygoteFork(); 106 107 // Grab thread before fork potentially makes Thread::pthread_key_self_ unusable. 108 Thread* self = Thread::Current(); 109 return reinterpret_cast<jlong>(self); 110 } 111 112 static void ZygoteHooks_nativePostForkChild(JNIEnv* env, jclass, jlong token, jint debug_flags, 113 jstring instruction_set) { 114 Thread* thread = reinterpret_cast<Thread*>(token); 115 // Our system thread ID, etc, has changed so reset Thread state. 116 thread->InitAfterFork(); 117 EnableDebugFeatures(debug_flags); 118 119 if (instruction_set != nullptr) { 120 ScopedUtfChars isa_string(env, instruction_set); 121 InstructionSet isa = GetInstructionSetFromString(isa_string.c_str()); 122 Runtime::NativeBridgeAction action = Runtime::NativeBridgeAction::kUnload; 123 if (isa != kNone && isa != kRuntimeISA) { 124 action = Runtime::NativeBridgeAction::kInitialize; 125 } 126 Runtime::Current()->DidForkFromZygote(env, action, isa_string.c_str()); 127 } else { 128 Runtime::Current()->DidForkFromZygote(env, Runtime::NativeBridgeAction::kUnload, nullptr); 129 } 130 } 131 132 static JNINativeMethod gMethods[] = { 133 NATIVE_METHOD(ZygoteHooks, nativePreFork, "()J"), 134 NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JILjava/lang/String;)V"), 135 }; 136 137 void register_dalvik_system_ZygoteHooks(JNIEnv* env) { 138 REGISTER_NATIVE_METHODS("dalvik/system/ZygoteHooks"); 139 } 140 141 } // namespace art 142