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