From 1cea0473a5a1f3124f0d3a95643c573296a2bac5 Mon Sep 17 00:00:00 2001 From: Justin Cohen Date: Wed, 20 Mar 2024 12:42:43 -0400 Subject: [PATCH] ios: Capture signal exception context memory regions correctly. Previously, Crashpad would only capture iOS thread context memory regions by iterating the task_threads->thread_get_state's. For Mach exception this worked as intended. However, for signal exceptions this missed the registers from the actual signal context. This change correctly captures these regions and stores them in the exception snapshot. Change-Id: I494e753a25c2687e61b5183ed0135f520ca8bf52 Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/5380505 Reviewed-by: Mark Mentovai Commit-Queue: Justin Cohen --- .../in_process_intermediate_dump_handler.cc | 16 ++++----- ...xception_snapshot_ios_intermediate_dump.cc | 34 +++++++++++++++++-- ...exception_snapshot_ios_intermediate_dump.h | 3 ++ ...ess_snapshot_ios_intermediate_dump_test.cc | 18 ++++++++++ 4 files changed, 61 insertions(+), 10 deletions(-) diff --git a/client/ios_handler/in_process_intermediate_dump_handler.cc b/client/ios_handler/in_process_intermediate_dump_handler.cc index 6cc6360d..29e26cb8 100644 --- a/client/ios_handler/in_process_intermediate_dump_handler.cc +++ b/client/ios_handler/in_process_intermediate_dump_handler.cc @@ -967,19 +967,19 @@ void InProcessIntermediateDumpHandler::WriteExceptionFromSignal( WriteProperty(writer, IntermediateDumpKey::kSignalNumber, &siginfo->si_signo); WriteProperty(writer, IntermediateDumpKey::kSignalCode, &siginfo->si_code); WriteProperty(writer, IntermediateDumpKey::kSignalAddress, &siginfo->si_addr); + #if defined(ARCH_CPU_X86_64) - WriteProperty( - writer, IntermediateDumpKey::kThreadState, &context->uc_mcontext->__ss); - WriteProperty( - writer, IntermediateDumpKey::kFloatState, &context->uc_mcontext->__fs); + x86_thread_state64_t thread_state = context->uc_mcontext->__ss; + x86_float_state64_t float_state = context->uc_mcontext->__fs; #elif defined(ARCH_CPU_ARM64) - WriteProperty( - writer, IntermediateDumpKey::kThreadState, &context->uc_mcontext->__ss); - WriteProperty( - writer, IntermediateDumpKey::kFloatState, &context->uc_mcontext->__ns); + arm_thread_state64_t thread_state = context->uc_mcontext->__ss; + arm_neon_state64_t float_state = context->uc_mcontext->__ns; #else #error Port to your CPU architecture #endif + WriteProperty(writer, IntermediateDumpKey::kThreadState, &thread_state); + WriteProperty(writer, IntermediateDumpKey::kFloatState, &float_state); + CaptureMemoryPointedToByThreadState(writer, thread_state); // Thread ID. thread_identifier_info identifier_info; diff --git a/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc b/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc index e3478454..9f1852a6 100644 --- a/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc +++ b/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc @@ -149,6 +149,33 @@ bool ExceptionSnapshotIOSIntermediateDump::InitializeFromSignal( GetDataValueFromMap(exception_data, Key::kSignalCode, &code); codes_.push_back(code); + const IOSIntermediateDumpList* thread_context_memory_regions = + GetListFromMap(exception_data, Key::kThreadContextMemoryRegions); + if (thread_context_memory_regions) { + for (auto& region : *thread_context_memory_regions) { + vm_address_t address; + const IOSIntermediateDumpData* region_data = + region->GetAsData(Key::kThreadContextMemoryRegionData); + if (!region_data) + continue; + if (GetDataValueFromMap( + region.get(), Key::kThreadContextMemoryRegionAddress, &address)) { + const std::vector& bytes = region_data->bytes(); + vm_size_t data_size = bytes.size(); + if (data_size == 0) + continue; + + const vm_address_t data = + reinterpret_cast(bytes.data()); + + auto memory = + std::make_unique(); + memory->Initialize(address, data, data_size); + extra_memory_.push_back(std::move(memory)); + } + } + } + INITIALIZATION_STATE_SET_VALID(initialized_); return true; } @@ -281,8 +308,11 @@ const std::vector& ExceptionSnapshotIOSIntermediateDump::Codes() std::vector ExceptionSnapshotIOSIntermediateDump::ExtraMemory() const { - INITIALIZATION_STATE_DCHECK_VALID(initialized_); - return std::vector(); + std::vector extra_memory; + for (const auto& memory : extra_memory_) { + extra_memory.push_back(memory.get()); + } + return extra_memory; } void ExceptionSnapshotIOSIntermediateDump::LoadContextFromThread( diff --git a/snapshot/ios/exception_snapshot_ios_intermediate_dump.h b/snapshot/ios/exception_snapshot_ios_intermediate_dump.h index 90966df1..dc9d5954 100644 --- a/snapshot/ios/exception_snapshot_ios_intermediate_dump.h +++ b/snapshot/ios/exception_snapshot_ios_intermediate_dump.h @@ -23,6 +23,7 @@ #include "build/build_config.h" #include "snapshot/cpu_context.h" #include "snapshot/exception_snapshot.h" +#include "snapshot/ios/memory_snapshot_ios_intermediate_dump.h" #include "util/ios/ios_intermediate_dump_map.h" #include "util/mach/mach_extensions.h" #include "util/misc/initialization_state_dcheck.h" @@ -106,6 +107,8 @@ class ExceptionSnapshotIOSIntermediateDump final : public ExceptionSnapshot { uintptr_t exception_address_; uint32_t exception_; uint32_t exception_info_; + std::vector> + extra_memory_; InitializationStateDcheck initialized_; }; diff --git a/snapshot/ios/process_snapshot_ios_intermediate_dump_test.cc b/snapshot/ios/process_snapshot_ios_intermediate_dump_test.cc index 29d26a83..69cb43ed 100644 --- a/snapshot/ios/process_snapshot_ios_intermediate_dump_test.cc +++ b/snapshot/ios/process_snapshot_ios_intermediate_dump_test.cc @@ -577,6 +577,18 @@ TEST_F(ProcessSnapshotIOSIntermediateDumpTest, EmptySignalDump) { IOSIntermediateDumpWriter::ScopedMap map(writer(), Key::kSignalException); uint64_t thread_id = 1; EXPECT_TRUE(writer()->AddProperty(Key::kThreadID, &thread_id)); + { + IOSIntermediateDumpWriter::ScopedArray contextMemoryRegions( + writer(), Key::kThreadContextMemoryRegions); + IOSIntermediateDumpWriter::ScopedArrayMap memoryMap(writer()); + + std::string random_data("random_data"); + EXPECT_TRUE(writer()->AddProperty( + Key::kThreadContextMemoryRegionAddress, &thread_id)); + EXPECT_TRUE(writer()->AddProperty(Key::kThreadContextMemoryRegionData, + random_data.c_str(), + random_data.length())); + } } { IOSIntermediateDumpWriter::ScopedArray threadArray(writer(), @@ -589,6 +601,12 @@ TEST_F(ProcessSnapshotIOSIntermediateDumpTest, EmptySignalDump) { CloseWriter(); ProcessSnapshotIOSIntermediateDump process_snapshot; ASSERT_TRUE(process_snapshot.InitializeWithFilePath(path(), annotations())); + EXPECT_EQ(process_snapshot.Exception()->ExtraMemory().size(), 1u); + ReadToString delegate; + for (auto memory : process_snapshot.Exception()->ExtraMemory()) { + memory->Read(&delegate); + EXPECT_STREQ(delegate.result.c_str(), "random_data"); + } EXPECT_FALSE(IsRegularFile(path())); EXPECT_TRUE(DumpSnapshot(process_snapshot)); }