diff options
author | 2023-08-11 10:21:26 +0200 | |
---|---|---|
committer | 2023-08-14 11:20:38 +0000 | |
commit | 32967de2c88fc675d9d3f43d6b5613f4fd93f769 (patch) | |
tree | fa548d234f220a12395741033ccee65d3b91f4b1 | |
parent | 258ac8d70c5a61682add86754f475137480c3a98 (diff) |
Detect bug 294339122 and crash with debugging output.
Test: run-gtests.sh
Test: testrunner.py --target --64 --optimizing
Bug: 294339122
Change-Id: I418783b7e80f7fb2ef54cab5d52717ab3bf039c8
-rw-r--r-- | runtime/fault_handler.cc | 43 | ||||
-rw-r--r-- | runtime/fault_handler.h | 7 |
2 files changed, 50 insertions, 0 deletions
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc index 7e5e745eef..75a14df32c 100644 --- a/runtime/fault_handler.cc +++ b/runtime/fault_handler.cc @@ -236,6 +236,47 @@ bool FaultManager::HandleSigbusFault(int sig, siginfo_t* info, [[maybe_unused]] return Runtime::Current()->GetHeap()->MarkCompactCollector()->SigbusHandler(info); } +inline void FaultManager::CheckForUnrecognizedImplicitSuspendCheckInBootImage( + siginfo_t* siginfo, void* context) { + CHECK_EQ(kRuntimeISA, InstructionSet::kArm64); + uintptr_t fault_pc = GetFaultPc(siginfo, context); + if (fault_pc == 0u || !IsUint<32>(fault_pc) || !IsAligned<4u>(fault_pc)) { + return; + } + Runtime* runtime = Runtime::Current(); + if (runtime == nullptr) { + return; + } + gc::Heap* heap = runtime->GetHeap(); + if (heap == nullptr || + fault_pc < heap->GetBootImagesStartAddress() || + fault_pc - heap->GetBootImagesStartAddress() >= heap->GetBootImagesSize() || + reinterpret_cast<uint32_t*>(fault_pc)[0] != /*LDR x21. [x21]*/ 0xf94002b5u) { + return; + } + std::ostringstream oss; + oss << "Failed to recognize implicit suspend check at 0x" << std::hex << fault_pc << "; "; + Thread* thread = Thread::Current(); + if (thread == nullptr) { + oss << "null thread"; + } else { + oss << "thread state = " << thread->GetState() << std::boolalpha + << "; mutator lock shared held = " << Locks::mutator_lock_->IsSharedHeld(thread); + } + oss << "; code ranges = {"; + GeneratedCodeRange* range = generated_code_ranges_.load(std::memory_order_acquire); + const char* s = ""; + while (range != nullptr) { + oss << s << "{" << range->start << ", " << range->size << "}"; + s = ", "; + range = range->next.load(std::memory_order_relaxed); + } + oss << "}"; + LOG(FATAL) << oss.str(); + UNREACHABLE(); +} + + bool FaultManager::HandleSigsegvFault(int sig, siginfo_t* info, void* context) { if (VLOG_IS_ON(signals)) { PrintSignalInfo(VLOG_STREAM(signals) << "Handling SIGSEGV fault:\n", info); @@ -256,6 +297,8 @@ bool FaultManager::HandleSigsegvFault(int sig, siginfo_t* info, void* context) { return true; } } + } else if (kRuntimeISA == InstructionSet::kArm64) { + CheckForUnrecognizedImplicitSuspendCheckInBootImage(info, context); } // We hit a signal we didn't handle. This might be something for which diff --git a/runtime/fault_handler.h b/runtime/fault_handler.h index 1ed65261b0..6be1743925 100644 --- a/runtime/fault_handler.h +++ b/runtime/fault_handler.h @@ -89,6 +89,13 @@ class FaultManager { bool HandleFaultByOtherHandlers(int sig, siginfo_t* info, void* context) NO_THREAD_SAFETY_ANALYSIS; + // Check if this is an implicit suspend check that was somehow not recognized as being + // in the compiled code. If that's the case, collect debugging data for the abort message + // and crash. Focus on suspend checks in the boot image. Bug: 294339122 + // NO_THREAD_SAFETY_ANALYSIS: Same as `IsInGeneratedCode()`. + void CheckForUnrecognizedImplicitSuspendCheckInBootImage(siginfo_t* siginfo, void* context) + NO_THREAD_SAFETY_ANALYSIS; + // Note: The lock guards modifications of the ranges but the function `IsInGeneratedCode()` // walks the list in the context of a signal handler without holding the lock. Mutex generated_code_ranges_lock_; |