summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2023-08-11 10:21:26 +0200
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2023-08-14 11:20:38 +0000
commit32967de2c88fc675d9d3f43d6b5613f4fd93f769 (patch)
treefa548d234f220a12395741033ccee65d3b91f4b1
parent258ac8d70c5a61682add86754f475137480c3a98 (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.cc43
-rw-r--r--runtime/fault_handler.h7
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_;