Detect bug 294339122 and crash with debugging output. (cherry picked from commit 32967de2c88fc675d9d3f43d6b5613f4fd93f769) Test: run-gtests.sh Test: testrunner.py --target --64 --optimizing Bug: 294339122 Merged-In: I418783b7e80f7fb2ef54cab5d52717ab3bf039c8 Change-Id: Iec745e0969649f161e42484b9f9af09955f75696
diff --git a/runtime/fault_handler.cc b/runtime/fault_handler.cc index a3c1f3b..652368c 100644 --- a/runtime/fault_handler.cc +++ b/runtime/fault_handler.cc
@@ -236,6 +236,47 @@ 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 @@ 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 1ed6526..6be1743 100644 --- a/runtime/fault_handler.h +++ b/runtime/fault_handler.h
@@ -89,6 +89,13 @@ 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_;