• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string.h>
20 #include <sys/mman.h>
21 #include <sys/ucontext.h>
22 
23 #include <atomic>
24 
25 #include "art_method-inl.h"
26 #include "base/logging.h"  // For VLOG
27 #include "base/membarrier.h"
28 #include "base/safe_copy.h"
29 #include "base/stl_util.h"
30 #include "dex/dex_file_types.h"
31 #include "gc/heap.h"
32 #include "jit/jit.h"
33 #include "jit/jit_code_cache.h"
34 #include "mirror/class.h"
35 #include "mirror/object_reference.h"
36 #include "oat_file.h"
37 #include "oat_quick_method_header.h"
38 #include "sigchain.h"
39 #include "thread-current-inl.h"
40 #include "verify_object-inl.h"
41 
42 namespace art {
43 // Static fault manger object accessed by signal handler.
44 FaultManager fault_manager;
45 
46 // This needs to be NO_INLINE since some debuggers do not read the inline-info to set a breakpoint
47 // if it isn't.
art_sigsegv_fault()48 extern "C" NO_INLINE __attribute__((visibility("default"))) void art_sigsegv_fault() {
49   // Set a breakpoint here to be informed when a SIGSEGV is unhandled by ART.
50   VLOG(signals)<< "Caught unknown SIGSEGV in ART fault handler - chaining to next handler.";
51 }
52 
53 // Signal handler called on SIGSEGV.
art_sigsegv_handler(int sig,siginfo_t * info,void * context)54 static bool art_sigsegv_handler(int sig, siginfo_t* info, void* context) {
55   return fault_manager.HandleSigsegvFault(sig, info, context);
56 }
57 
58 // Signal handler called on SIGBUS.
art_sigbus_handler(int sig,siginfo_t * info,void * context)59 static bool art_sigbus_handler(int sig, siginfo_t* info, void* context) {
60   return fault_manager.HandleSigbusFault(sig, info, context);
61 }
62 
FaultManager()63 FaultManager::FaultManager()
64     : generated_code_ranges_lock_("FaultHandler generated code ranges lock",
65                                   LockLevel::kGenericBottomLock),
66       initialized_(false) {}
67 
~FaultManager()68 FaultManager::~FaultManager() {
69 }
70 
SignalCodeName(int sig,int code)71 static const char* SignalCodeName(int sig, int code) {
72   if (sig == SIGSEGV) {
73     switch (code) {
74       case SEGV_MAPERR: return "SEGV_MAPERR";
75       case SEGV_ACCERR: return "SEGV_ACCERR";
76       case 8:           return "SEGV_MTEAERR";
77       case 9:           return "SEGV_MTESERR";
78       default:          return "SEGV_UNKNOWN";
79     }
80   } else if (sig == SIGBUS) {
81     switch (code) {
82       case BUS_ADRALN: return "BUS_ADRALN";
83       case BUS_ADRERR: return "BUS_ADRERR";
84       case BUS_OBJERR: return "BUS_OBJERR";
85       default:         return "BUS_UNKNOWN";
86     }
87   } else {
88     return "UNKNOWN";
89   }
90 }
91 
PrintSignalInfo(std::ostream & os,siginfo_t * info)92 static std::ostream& PrintSignalInfo(std::ostream& os, siginfo_t* info) {
93   os << "  si_signo: " << info->si_signo << " (" << strsignal(info->si_signo) << ")\n"
94      << "  si_code: " << info->si_code
95      << " (" << SignalCodeName(info->si_signo, info->si_code) << ")";
96   if (info->si_signo == SIGSEGV || info->si_signo == SIGBUS) {
97     os << "\n" << "  si_addr: " << info->si_addr;
98   }
99   return os;
100 }
101 
InstallSigbusHandler()102 static bool InstallSigbusHandler() {
103   return gUseUserfaultfd &&
104          Runtime::Current()->GetHeap()->MarkCompactCollector()->IsUsingSigbusFeature();
105 }
106 
Init(bool use_sig_chain)107 void FaultManager::Init(bool use_sig_chain) {
108   CHECK(!initialized_);
109   if (use_sig_chain) {
110     sigset_t mask;
111     sigfillset(&mask);
112     sigdelset(&mask, SIGABRT);
113     sigdelset(&mask, SIGBUS);
114     sigdelset(&mask, SIGFPE);
115     sigdelset(&mask, SIGILL);
116     sigdelset(&mask, SIGSEGV);
117 
118     SigchainAction sa = {
119         .sc_sigaction = art_sigsegv_handler,
120         .sc_mask = mask,
121         .sc_flags = 0UL,
122     };
123 
124     AddSpecialSignalHandlerFn(SIGSEGV, &sa);
125     if (InstallSigbusHandler()) {
126       sa.sc_sigaction = art_sigbus_handler;
127       AddSpecialSignalHandlerFn(SIGBUS, &sa);
128     }
129 
130     // Notify the kernel that we intend to use a specific `membarrier()` command.
131     int result = art::membarrier(MembarrierCommand::kRegisterPrivateExpedited);
132     if (result != 0) {
133       LOG(WARNING) << "FaultHandler: MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED failed: "
134                    << errno << " " << strerror(errno);
135     }
136 
137     {
138       MutexLock lock(Thread::Current(), generated_code_ranges_lock_);
139       for (size_t i = 0; i != kNumLocalGeneratedCodeRanges; ++i) {
140         GeneratedCodeRange* next = (i + 1u != kNumLocalGeneratedCodeRanges)
141             ? &generated_code_ranges_storage_[i + 1u]
142             : nullptr;
143         generated_code_ranges_storage_[i].next.store(next, std::memory_order_relaxed);
144         generated_code_ranges_storage_[i].start = nullptr;
145         generated_code_ranges_storage_[i].size = 0u;
146       }
147       free_generated_code_ranges_ = generated_code_ranges_storage_;
148     }
149 
150     initialized_ = true;
151   } else if (InstallSigbusHandler()) {
152     struct sigaction act;
153     std::memset(&act, '\0', sizeof(act));
154     act.sa_flags = SA_SIGINFO | SA_RESTART;
155     act.sa_sigaction = [](int sig, siginfo_t* info, void* context) {
156       if (!art_sigbus_handler(sig, info, context)) {
157         std::ostringstream oss;
158         PrintSignalInfo(oss, info);
159         LOG(FATAL) << "Couldn't handle SIGBUS fault:"
160                    << "\n"
161                    << oss.str();
162       }
163     };
164     if (sigaction(SIGBUS, &act, nullptr)) {
165       LOG(FATAL) << "Fault handler for SIGBUS couldn't be setup: " << strerror(errno);
166     }
167   }
168 }
169 
Release()170 void FaultManager::Release() {
171   if (initialized_) {
172     RemoveSpecialSignalHandlerFn(SIGSEGV, art_sigsegv_handler);
173     if (InstallSigbusHandler()) {
174       RemoveSpecialSignalHandlerFn(SIGBUS, art_sigbus_handler);
175     }
176     initialized_ = false;
177   }
178 }
179 
Shutdown()180 void FaultManager::Shutdown() {
181   if (initialized_) {
182     Release();
183 
184     // Free all handlers.
185     STLDeleteElements(&generated_code_handlers_);
186     STLDeleteElements(&other_handlers_);
187 
188     // Delete remaining code ranges if any (such as nterp code or oat code from
189     // oat files that have not been unloaded, including boot image oat files).
190     MutexLock lock(Thread::Current(), generated_code_ranges_lock_);
191     GeneratedCodeRange* range = generated_code_ranges_.load(std::memory_order_acquire);
192     generated_code_ranges_.store(nullptr, std::memory_order_release);
193     while (range != nullptr) {
194       GeneratedCodeRange* next_range = range->next.load(std::memory_order_relaxed);
195       std::less<GeneratedCodeRange*> less;
196       if (!less(range, generated_code_ranges_storage_) &&
197           less(range, generated_code_ranges_storage_ + kNumLocalGeneratedCodeRanges)) {
198         // Nothing to do - not adding `range` to the `free_generated_code_ranges_` anymore.
199       } else {
200         // Range is not in the `generated_code_ranges_storage_`.
201         delete range;
202       }
203       range = next_range;
204     }
205   }
206 }
207 
HandleFaultByOtherHandlers(int sig,siginfo_t * info,void * context)208 bool FaultManager::HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context) {
209   if (other_handlers_.empty()) {
210     return false;
211   }
212 
213   Thread* self = Thread::Current();
214 
215   DCHECK(self != nullptr);
216   DCHECK(Runtime::Current() != nullptr);
217   DCHECK(Runtime::Current()->IsStarted());
218   for (const auto& handler : other_handlers_) {
219     if (handler->Action(sig, info, context)) {
220       return true;
221     }
222   }
223   return false;
224 }
225 
HandleSigbusFault(int sig,siginfo_t * info,void * context ATTRIBUTE_UNUSED)226 bool FaultManager::HandleSigbusFault(int sig, siginfo_t* info, void* context ATTRIBUTE_UNUSED) {
227   DCHECK_EQ(sig, SIGBUS);
228   if (VLOG_IS_ON(signals)) {
229     PrintSignalInfo(VLOG_STREAM(signals) << "Handling SIGBUS fault:\n", info);
230   }
231 
232 #ifdef TEST_NESTED_SIGNAL
233   // Simulate a crash in a handler.
234   raise(SIGBUS);
235 #endif
236   return Runtime::Current()->GetHeap()->MarkCompactCollector()->SigbusHandler(info);
237 }
238 
HandleSigsegvFault(int sig,siginfo_t * info,void * context)239 bool FaultManager::HandleSigsegvFault(int sig, siginfo_t* info, void* context) {
240   if (VLOG_IS_ON(signals)) {
241     PrintSignalInfo(VLOG_STREAM(signals) << "Handling SIGSEGV fault:\n", info);
242   }
243 
244 #ifdef TEST_NESTED_SIGNAL
245   // Simulate a crash in a handler.
246   raise(SIGSEGV);
247 #endif
248 
249   if (IsInGeneratedCode(info, context)) {
250     VLOG(signals) << "in generated code, looking for handler";
251     for (const auto& handler : generated_code_handlers_) {
252       VLOG(signals) << "invoking Action on handler " << handler;
253       if (handler->Action(sig, info, context)) {
254         // We have handled a signal so it's time to return from the
255         // signal handler to the appropriate place.
256         return true;
257       }
258     }
259   }
260 
261   // We hit a signal we didn't handle.  This might be something for which
262   // we can give more information about so call all registered handlers to
263   // see if it is.
264   if (HandleFaultByOtherHandlers(sig, info, context)) {
265     return true;
266   }
267 
268   // Set a breakpoint in this function to catch unhandled signals.
269   art_sigsegv_fault();
270   return false;
271 }
272 
AddHandler(FaultHandler * handler,bool generated_code)273 void FaultManager::AddHandler(FaultHandler* handler, bool generated_code) {
274   DCHECK(initialized_);
275   if (generated_code) {
276     generated_code_handlers_.push_back(handler);
277   } else {
278     other_handlers_.push_back(handler);
279   }
280 }
281 
RemoveHandler(FaultHandler * handler)282 void FaultManager::RemoveHandler(FaultHandler* handler) {
283   auto it = std::find(generated_code_handlers_.begin(), generated_code_handlers_.end(), handler);
284   if (it != generated_code_handlers_.end()) {
285     generated_code_handlers_.erase(it);
286     return;
287   }
288   auto it2 = std::find(other_handlers_.begin(), other_handlers_.end(), handler);
289   if (it2 != other_handlers_.end()) {
290     other_handlers_.erase(it2);
291     return;
292   }
293   LOG(FATAL) << "Attempted to remove non existent handler " << handler;
294 }
295 
CreateGeneratedCodeRange(const void * start,size_t size)296 inline FaultManager::GeneratedCodeRange* FaultManager::CreateGeneratedCodeRange(
297     const void* start, size_t size) {
298   GeneratedCodeRange* range = free_generated_code_ranges_;
299   if (range != nullptr) {
300     std::less<GeneratedCodeRange*> less;
301     DCHECK(!less(range, generated_code_ranges_storage_));
302     DCHECK(less(range, generated_code_ranges_storage_ + kNumLocalGeneratedCodeRanges));
303     range->start = start;
304     range->size = size;
305     free_generated_code_ranges_ = range->next.load(std::memory_order_relaxed);
306     range->next.store(nullptr, std::memory_order_relaxed);
307     return range;
308   } else {
309     return new GeneratedCodeRange{nullptr, start, size};
310   }
311 }
312 
FreeGeneratedCodeRange(GeneratedCodeRange * range)313 inline void FaultManager::FreeGeneratedCodeRange(GeneratedCodeRange* range) {
314   std::less<GeneratedCodeRange*> less;
315   if (!less(range, generated_code_ranges_storage_) &&
316       less(range, generated_code_ranges_storage_ + kNumLocalGeneratedCodeRanges)) {
317     MutexLock lock(Thread::Current(), generated_code_ranges_lock_);
318     range->start = nullptr;
319     range->size = 0u;
320     range->next.store(free_generated_code_ranges_, std::memory_order_relaxed);
321     free_generated_code_ranges_ = range;
322   } else {
323     // Range is not in the `generated_code_ranges_storage_`.
324     delete range;
325   }
326 }
327 
AddGeneratedCodeRange(const void * start,size_t size)328 void FaultManager::AddGeneratedCodeRange(const void* start, size_t size) {
329   GeneratedCodeRange* new_range = nullptr;
330   {
331     MutexLock lock(Thread::Current(), generated_code_ranges_lock_);
332     new_range = CreateGeneratedCodeRange(start, size);
333     GeneratedCodeRange* old_head = generated_code_ranges_.load(std::memory_order_relaxed);
334     new_range->next.store(old_head, std::memory_order_relaxed);
335     generated_code_ranges_.store(new_range, std::memory_order_release);
336   }
337 
338   // The above release operation on `generated_code_ranges_` with an acquire operation
339   // on the same atomic object in `IsInGeneratedCode()` ensures the correct memory
340   // visibility for the contents of `*new_range` for any thread that loads the value
341   // written above (or a value written by a release sequence headed by that write).
342   //
343   // However, we also need to ensure that any thread that encounters a segmentation
344   // fault in the provided range shall actually see the written value. For JIT code
345   // cache and nterp, the registration happens while the process is single-threaded
346   // but the synchronization is more complicated for code in oat files.
347   //
348   // Threads that load classes register dex files under the `Locks::dex_lock_` and
349   // the first one to register a dex file with a given oat file shall add the oat
350   // code range; the memory visibility for these threads is guaranteed by the lock.
351   // However a thread that did not try to load a class with oat code can execute the
352   // code if a direct or indirect reference to such class escapes from one of the
353   // threads that loaded it. Use `membarrier()` for memory visibility in this case.
354   art::membarrier(MembarrierCommand::kPrivateExpedited);
355 }
356 
RemoveGeneratedCodeRange(const void * start,size_t size)357 void FaultManager::RemoveGeneratedCodeRange(const void* start, size_t size) {
358   Thread* self = Thread::Current();
359   GeneratedCodeRange* range = nullptr;
360   {
361     MutexLock lock(self, generated_code_ranges_lock_);
362     std::atomic<GeneratedCodeRange*>* before = &generated_code_ranges_;
363     range = before->load(std::memory_order_relaxed);
364     while (range != nullptr && range->start != start) {
365       before = &range->next;
366       range = before->load(std::memory_order_relaxed);
367     }
368     if (range != nullptr) {
369       GeneratedCodeRange* next = range->next.load(std::memory_order_relaxed);
370       if (before == &generated_code_ranges_) {
371         // Relaxed store directly to `generated_code_ranges_` would not satisfy
372         // conditions for a release sequence, so we need to use store-release.
373         before->store(next, std::memory_order_release);
374       } else {
375         // In the middle of the list, we can use a relaxed store as we're not
376         // publishing any newly written memory to potential reader threads.
377         // Whether they see the removed node or not is unimportant as we should
378         // not execute that code anymore. We're keeping the `next` link of the
379         // removed node, so that concurrent walk can use it to reach remaining
380         // retained nodes, if any.
381         before->store(next, std::memory_order_relaxed);
382       }
383     }
384   }
385   CHECK(range != nullptr);
386   DCHECK_EQ(range->start, start);
387   CHECK_EQ(range->size, size);
388 
389   Runtime* runtime = Runtime::Current();
390   CHECK(runtime != nullptr);
391   if (runtime->IsStarted() && runtime->GetThreadList() != nullptr) {
392     // Run a checkpoint before deleting the range to ensure that no thread holds a
393     // pointer to the removed range while walking the list in `IsInGeneratedCode()`.
394     // That walk is guarded by checking that the thread is `Runnable`, so any walk
395     // started before the removal shall be done when running the checkpoint and the
396     // checkpoint also ensures the correct memory visibility of `next` links,
397     // so the thread shall not see the pointer during future walks.
398 
399     // This function is currently called in different mutex and thread states.
400     // Semi-space GC performs the cleanup during its `MarkingPhase()` while holding
401     // the mutator exclusively, so we do not need a checkpoint. All other GCs perform
402     // the cleanup in their `ReclaimPhase()` while holding the mutator lock as shared
403     // and it's safe to release and re-acquire the mutator lock. Despite holding the
404     // mutator lock as shared, the thread is not always marked as `Runnable`.
405     // TODO: Clean up state transitions in different GC implementations. b/259440389
406     if (Locks::mutator_lock_->IsExclusiveHeld(self)) {
407       // We do not need a checkpoint because no other thread is Runnable.
408     } else {
409       DCHECK(Locks::mutator_lock_->IsSharedHeld(self));
410       // Use explicit state transitions or unlock/lock.
411       bool runnable = (self->GetState() == ThreadState::kRunnable);
412       if (runnable) {
413         self->TransitionFromRunnableToSuspended(ThreadState::kNative);
414       } else {
415         Locks::mutator_lock_->SharedUnlock(self);
416       }
417       DCHECK(!Locks::mutator_lock_->IsSharedHeld(self));
418       runtime->GetThreadList()->RunEmptyCheckpoint();
419       if (runnable) {
420         self->TransitionFromSuspendedToRunnable();
421       } else {
422         Locks::mutator_lock_->SharedLock(self);
423       }
424     }
425   }
426   FreeGeneratedCodeRange(range);
427 }
428 
429 // This function is called within the signal handler. It checks that the thread
430 // is `Runnable`, the `mutator_lock_` is held (shared) and the fault PC is in one
431 // of the registered generated code ranges. No annotalysis is done.
IsInGeneratedCode(siginfo_t * siginfo,void * context)432 bool FaultManager::IsInGeneratedCode(siginfo_t* siginfo, void* context) {
433   // We can only be running Java code in the current thread if it
434   // is in Runnable state.
435   VLOG(signals) << "Checking for generated code";
436   Thread* thread = Thread::Current();
437   if (thread == nullptr) {
438     VLOG(signals) << "no current thread";
439     return false;
440   }
441 
442   ThreadState state = thread->GetState();
443   if (state != ThreadState::kRunnable) {
444     VLOG(signals) << "not runnable";
445     return false;
446   }
447 
448   // Current thread is runnable.
449   // Make sure it has the mutator lock.
450   if (!Locks::mutator_lock_->IsSharedHeld(thread)) {
451     VLOG(signals) << "no lock";
452     return false;
453   }
454 
455   uintptr_t fault_pc = GetFaultPc(siginfo, context);
456   if (fault_pc == 0u) {
457     VLOG(signals) << "no fault PC";
458     return false;
459   }
460 
461   // Walk over the list of registered code ranges.
462   GeneratedCodeRange* range = generated_code_ranges_.load(std::memory_order_acquire);
463   while (range != nullptr) {
464     if (fault_pc - reinterpret_cast<uintptr_t>(range->start) < range->size) {
465       return true;
466     }
467     // We may or may not see ranges that were concurrently removed, depending
468     // on when the relaxed writes of the `next` links become visible. However,
469     // even if we're currently at a node that is being removed, we shall visit
470     // all remaining ranges that are not being removed as the removed nodes
471     // retain the `next` link at the time of removal (which may lead to other
472     // removed nodes before reaching remaining retained nodes, if any). Correct
473     // memory visibility of `start` and `size` fields of the visited ranges is
474     // ensured by the release and acquire operations on `generated_code_ranges_`.
475     range = range->next.load(std::memory_order_relaxed);
476   }
477   return false;
478 }
479 
FaultHandler(FaultManager * manager)480 FaultHandler::FaultHandler(FaultManager* manager) : manager_(manager) {
481 }
482 
483 //
484 // Null pointer fault handler
485 //
NullPointerHandler(FaultManager * manager)486 NullPointerHandler::NullPointerHandler(FaultManager* manager) : FaultHandler(manager) {
487   manager_->AddHandler(this, true);
488 }
489 
IsValidMethod(ArtMethod * method)490 bool NullPointerHandler::IsValidMethod(ArtMethod* method) {
491   // At this point we know that the thread is `Runnable` and the PC is in one of
492   // the registered code ranges. The `method` was read from the top of the stack
493   // and should really point to an actual `ArtMethod`, unless we're crashing during
494   // prologue or epilogue, or somehow managed to jump to the compiled code by some
495   // unexpected path, other than method invoke or exception delivery. We do a few
496   // quick checks without guarding from another fault.
497   VLOG(signals) << "potential method: " << method;
498 
499   static_assert(IsAligned<sizeof(void*)>(ArtMethod::Size(kRuntimePointerSize)));
500   if (method == nullptr || !IsAligned<sizeof(void*)>(method)) {
501     VLOG(signals) << ((method == nullptr) ? "null method" : "unaligned method");
502     return false;
503   }
504 
505   // Check that the presumed method actually points to a class. Read barriers
506   // are not needed (and would be undesirable in a signal handler) when reading
507   // a chain of constant references to get to a non-movable `Class.class` object.
508 
509   // Note: Allowing nested faults. Checking that the method is in one of the
510   // `LinearAlloc` spaces, or that objects we look at are in the `Heap` would be
511   // slow and require locking a mutex, which is undesirable in a signal handler.
512   // (Though we could register valid ranges similarly to the generated code ranges.)
513 
514   mirror::Object* klass =
515       method->GetDeclaringClassAddressWithoutBarrier()->AsMirrorPtr();
516   if (klass == nullptr || !IsAligned<kObjectAlignment>(klass)) {
517     VLOG(signals) << ((klass == nullptr) ? "null class" : "unaligned class");
518     return false;
519   }
520 
521   mirror::Class* class_class = klass->GetClass<kVerifyNone, kWithoutReadBarrier>();
522   if (class_class == nullptr || !IsAligned<kObjectAlignment>(class_class)) {
523     VLOG(signals) << ((klass == nullptr) ? "null class_class" : "unaligned class_class");
524     return false;
525   }
526 
527   if (class_class != class_class->GetClass<kVerifyNone, kWithoutReadBarrier>()) {
528     VLOG(signals) << "invalid class_class";
529     return false;
530   }
531 
532   return true;
533 }
534 
IsValidReturnPc(ArtMethod ** sp,uintptr_t return_pc)535 bool NullPointerHandler::IsValidReturnPc(ArtMethod** sp, uintptr_t return_pc) {
536   // Check if we can associate a dex PC with the return PC, whether from Nterp,
537   // or with an existing stack map entry for a compiled method.
538   // Note: Allowing nested faults if `IsValidMethod()` returned a false positive.
539   // Note: The `ArtMethod::GetOatQuickMethodHeader()` can acquire locks (at least
540   // `Locks::jit_lock_`) and if the thread already held such a lock, the signal
541   // handler would deadlock. However, if a thread is holding one of the locks
542   // below the mutator lock, the PC should be somewhere in ART code and should
543   // not match any registered generated code range, so such as a deadlock is
544   // unlikely. If it happens anyway, the worst case is that an internal ART crash
545   // would be reported as ANR.
546   ArtMethod* method = *sp;
547   const OatQuickMethodHeader* method_header = method->GetOatQuickMethodHeader(return_pc);
548   if (method_header == nullptr) {
549     VLOG(signals) << "No method header.";
550     return false;
551   }
552   VLOG(signals) << "looking for dex pc for return pc 0x" << std::hex << return_pc
553                 << " pc offset: 0x" << std::hex
554                 << (return_pc - reinterpret_cast<uintptr_t>(method_header->GetEntryPoint()));
555   uint32_t dexpc = method_header->ToDexPc(reinterpret_cast<ArtMethod**>(sp), return_pc, false);
556   VLOG(signals) << "dexpc: " << dexpc;
557   return dexpc != dex::kDexNoIndex;
558 }
559 
560 //
561 // Suspension fault handler
562 //
SuspensionHandler(FaultManager * manager)563 SuspensionHandler::SuspensionHandler(FaultManager* manager) : FaultHandler(manager) {
564   manager_->AddHandler(this, true);
565 }
566 
567 //
568 // Stack overflow fault handler
569 //
StackOverflowHandler(FaultManager * manager)570 StackOverflowHandler::StackOverflowHandler(FaultManager* manager) : FaultHandler(manager) {
571   manager_->AddHandler(this, true);
572 }
573 
574 //
575 // Stack trace handler, used to help get a stack trace from SIGSEGV inside of compiled code.
576 //
JavaStackTraceHandler(FaultManager * manager)577 JavaStackTraceHandler::JavaStackTraceHandler(FaultManager* manager) : FaultHandler(manager) {
578   manager_->AddHandler(this, false);
579 }
580 
Action(int sig ATTRIBUTE_UNUSED,siginfo_t * siginfo,void * context)581 bool JavaStackTraceHandler::Action(int sig ATTRIBUTE_UNUSED, siginfo_t* siginfo, void* context) {
582   // Make sure that we are in the generated code, but we may not have a dex pc.
583   bool in_generated_code = manager_->IsInGeneratedCode(siginfo, context);
584   if (in_generated_code) {
585     LOG(ERROR) << "Dumping java stack trace for crash in generated code";
586     Thread* self = Thread::Current();
587 
588     uintptr_t sp = FaultManager::GetFaultSp(context);
589     CHECK_NE(sp, 0u);  // Otherwise we should not have reached this handler.
590     // Inside of generated code, sp[0] is the method, so sp is the frame.
591     self->SetTopOfStack(reinterpret_cast<ArtMethod**>(sp));
592     self->DumpJavaStack(LOG_STREAM(ERROR));
593   }
594 
595   return false;  // Return false since we want to propagate the fault to the main signal handler.
596 }
597 
598 }   // namespace art
599