fault_handler.cc revision 147eb41b53729ec8d5c188d1cac90964a51afb8a
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 "fault_handler.h" 18#include <sys/mman.h> 19#include <sys/ucontext.h> 20#include "mirror/art_method.h" 21#include "mirror/class.h" 22#include "sigchain.h" 23#include "thread-inl.h" 24#include "verify_object-inl.h" 25 26namespace art { 27// Static fault manger object accessed by signal handler. 28FaultManager fault_manager; 29 30extern "C" { 31void art_sigsegv_fault() { 32 // Set a breakpoint here to be informed when a SIGSEGV is unhandled by ART. 33 VLOG(signals)<< "Caught unknown SIGSEGV in ART fault handler - chaining to next handler."; 34} 35} 36 37// Signal handler called on SIGSEGV. 38static void art_fault_handler(int sig, siginfo_t* info, void* context) { 39 // std::cout << "handling fault in ART handler\n"; 40 fault_manager.HandleFault(sig, info, context); 41} 42 43FaultManager::FaultManager() { 44 sigaction(SIGSEGV, nullptr, &oldaction_); 45} 46 47FaultManager::~FaultManager() { 48} 49 50 51void FaultManager::Init() { 52 struct sigaction action; 53 action.sa_sigaction = art_fault_handler; 54 sigemptyset(&action.sa_mask); 55 action.sa_flags = SA_SIGINFO | SA_ONSTACK; 56#if !defined(__APPLE__) && !defined(__mips__) 57 action.sa_restorer = nullptr; 58#endif 59 60 // Set our signal handler now. 61 int e = sigaction(SIGSEGV, &action, &oldaction_); 62 if (e != 0) { 63 VLOG(signals) << "Failed to claim SEGV: " << strerror(errno); 64 } 65 // Make sure our signal handler is called before any user handlers. 66 ClaimSignalChain(SIGSEGV, &oldaction_); 67} 68 69void FaultManager::HandleFault(int sig, siginfo_t* info, void* context) { 70 // BE CAREFUL ALLOCATING HERE INCLUDING USING LOG(...) 71 // 72 // If malloc calls abort, it will be holding its lock. 73 // If the handler tries to call malloc, it will deadlock. 74 75 // Also, there is only an 8K stack available here to logging can cause memory 76 // overwrite issues if you are unlucky. If you want to enable logging and 77 // are getting crashes, allocate more space for the alternate signal stack. 78 VLOG(signals) << "Handling fault"; 79 if (IsInGeneratedCode(info, context, true)) { 80 VLOG(signals) << "in generated code, looking for handler"; 81 for (const auto& handler : generated_code_handlers_) { 82 VLOG(signals) << "invoking Action on handler " << handler; 83 if (handler->Action(sig, info, context)) { 84 return; 85 } 86 } 87 } 88 for (const auto& handler : other_handlers_) { 89 if (handler->Action(sig, info, context)) { 90 return; 91 } 92 } 93 art_sigsegv_fault(); 94 95 // Pass this on to the next handler in the chain, or the default if none. 96 InvokeUserSignalHandler(sig, info, context); 97} 98 99void FaultManager::AddHandler(FaultHandler* handler, bool generated_code) { 100 if (generated_code) { 101 generated_code_handlers_.push_back(handler); 102 } else { 103 other_handlers_.push_back(handler); 104 } 105} 106 107void FaultManager::RemoveHandler(FaultHandler* handler) { 108 auto it = std::find(generated_code_handlers_.begin(), generated_code_handlers_.end(), handler); 109 if (it != generated_code_handlers_.end()) { 110 generated_code_handlers_.erase(it); 111 return; 112 } 113 auto it2 = std::find(other_handlers_.begin(), other_handlers_.end(), handler); 114 if (it2 != other_handlers_.end()) { 115 other_handlers_.erase(it); 116 return; 117 } 118 LOG(FATAL) << "Attempted to remove non existent handler " << handler; 119} 120 121// This function is called within the signal handler. It checks that 122// the mutator_lock is held (shared). No annotalysis is done. 123bool FaultManager::IsInGeneratedCode(siginfo_t* siginfo, void* context, bool check_dex_pc) { 124 // We can only be running Java code in the current thread if it 125 // is in Runnable state. 126 VLOG(signals) << "Checking for generated code"; 127 Thread* thread = Thread::Current(); 128 if (thread == nullptr) { 129 VLOG(signals) << "no current thread"; 130 return false; 131 } 132 133 ThreadState state = thread->GetState(); 134 if (state != kRunnable) { 135 VLOG(signals) << "not runnable"; 136 return false; 137 } 138 139 // Current thread is runnable. 140 // Make sure it has the mutator lock. 141 if (!Locks::mutator_lock_->IsSharedHeld(thread)) { 142 VLOG(signals) << "no lock"; 143 return false; 144 } 145 146 mirror::ArtMethod* method_obj = 0; 147 uintptr_t return_pc = 0; 148 uintptr_t sp = 0; 149 150 // Get the architecture specific method address and return address. These 151 // are in architecture specific files in arch/<arch>/fault_handler_<arch>. 152 GetMethodAndReturnPCAndSP(siginfo, context, &method_obj, &return_pc, &sp); 153 154 // If we don't have a potential method, we're outta here. 155 VLOG(signals) << "potential method: " << method_obj; 156 if (method_obj == 0 || !IsAligned<kObjectAlignment>(method_obj)) { 157 VLOG(signals) << "no method"; 158 return false; 159 } 160 161 // Verify that the potential method is indeed a method. 162 // TODO: check the GC maps to make sure it's an object. 163 // Check that the class pointer inside the object is not null and is aligned. 164 // TODO: Method might be not a heap address, and GetClass could fault. 165 mirror::Class* cls = method_obj->GetClass<kVerifyNone>(); 166 if (cls == nullptr) { 167 VLOG(signals) << "not a class"; 168 return false; 169 } 170 if (!IsAligned<kObjectAlignment>(cls)) { 171 VLOG(signals) << "not aligned"; 172 return false; 173 } 174 175 176 if (!VerifyClassClass(cls)) { 177 VLOG(signals) << "not a class class"; 178 return false; 179 } 180 181 // Now make sure the class is a mirror::ArtMethod. 182 if (!cls->IsArtMethodClass()) { 183 VLOG(signals) << "not a method"; 184 return false; 185 } 186 187 // We can be certain that this is a method now. Check if we have a GC map 188 // at the return PC address. 189 if (true || kIsDebugBuild) { 190 VLOG(signals) << "looking for dex pc for return pc " << std::hex << return_pc; 191 const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(method_obj); 192 uint32_t sought_offset = return_pc - reinterpret_cast<uintptr_t>(code); 193 VLOG(signals) << "pc offset: " << std::hex << sought_offset; 194 } 195 uint32_t dexpc = method_obj->ToDexPc(return_pc, false); 196 VLOG(signals) << "dexpc: " << dexpc; 197 return !check_dex_pc || dexpc != DexFile::kDexNoIndex; 198} 199 200FaultHandler::FaultHandler(FaultManager* manager) : manager_(manager) { 201} 202 203// 204// Null pointer fault handler 205// 206NullPointerHandler::NullPointerHandler(FaultManager* manager) : FaultHandler(manager) { 207 manager_->AddHandler(this, true); 208} 209 210// 211// Suspension fault handler 212// 213SuspensionHandler::SuspensionHandler(FaultManager* manager) : FaultHandler(manager) { 214 manager_->AddHandler(this, true); 215} 216 217// 218// Stack overflow fault handler 219// 220StackOverflowHandler::StackOverflowHandler(FaultManager* manager) : FaultHandler(manager) { 221 manager_->AddHandler(this, true); 222} 223 224// 225// Stack trace handler, used to help get a stack trace from SIGSEGV inside of compiled code. 226// 227JavaStackTraceHandler::JavaStackTraceHandler(FaultManager* manager) : FaultHandler(manager) { 228 manager_->AddHandler(this, false); 229} 230 231bool JavaStackTraceHandler::Action(int sig, siginfo_t* siginfo, void* context) { 232 // Make sure that we are in the generated code, but we may not have a dex pc. 233 if (manager_->IsInGeneratedCode(siginfo, context, false)) { 234 LOG(ERROR) << "Dumping java stack trace for crash in generated code"; 235 mirror::ArtMethod* method = nullptr; 236 uintptr_t return_pc = 0; 237 uintptr_t sp = 0; 238 manager_->GetMethodAndReturnPCAndSP(siginfo, context, &method, &return_pc, &sp); 239 Thread* self = Thread::Current(); 240 // Inside of generated code, sp[0] is the method, so sp is the frame. 241 StackReference<mirror::ArtMethod>* frame = 242 reinterpret_cast<StackReference<mirror::ArtMethod>*>(sp); 243 self->SetTopOfStack(frame, 0); // Since we don't necessarily have a dex pc, pass in 0. 244 self->DumpJavaStack(LOG(ERROR)); 245 } 246 return false; // Return false since we want to propagate the fault to the main signal handler. 247} 248 249} // namespace art 250 251