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 <mark@chromium.org>
Commit-Queue: Justin Cohen <justincohen@chromium.org>
This commit is contained in:
Justin Cohen 2024-03-20 12:42:43 -04:00 committed by Crashpad LUCI CQ
parent ccd20652bc
commit 1cea0473a5
4 changed files with 61 additions and 10 deletions

View File

@ -967,19 +967,19 @@ void InProcessIntermediateDumpHandler::WriteExceptionFromSignal(
WriteProperty(writer, IntermediateDumpKey::kSignalNumber, &siginfo->si_signo); WriteProperty(writer, IntermediateDumpKey::kSignalNumber, &siginfo->si_signo);
WriteProperty(writer, IntermediateDumpKey::kSignalCode, &siginfo->si_code); WriteProperty(writer, IntermediateDumpKey::kSignalCode, &siginfo->si_code);
WriteProperty(writer, IntermediateDumpKey::kSignalAddress, &siginfo->si_addr); WriteProperty(writer, IntermediateDumpKey::kSignalAddress, &siginfo->si_addr);
#if defined(ARCH_CPU_X86_64) #if defined(ARCH_CPU_X86_64)
WriteProperty( x86_thread_state64_t thread_state = context->uc_mcontext->__ss;
writer, IntermediateDumpKey::kThreadState, &context->uc_mcontext->__ss); x86_float_state64_t float_state = context->uc_mcontext->__fs;
WriteProperty(
writer, IntermediateDumpKey::kFloatState, &context->uc_mcontext->__fs);
#elif defined(ARCH_CPU_ARM64) #elif defined(ARCH_CPU_ARM64)
WriteProperty( arm_thread_state64_t thread_state = context->uc_mcontext->__ss;
writer, IntermediateDumpKey::kThreadState, &context->uc_mcontext->__ss); arm_neon_state64_t float_state = context->uc_mcontext->__ns;
WriteProperty(
writer, IntermediateDumpKey::kFloatState, &context->uc_mcontext->__ns);
#else #else
#error Port to your CPU architecture #error Port to your CPU architecture
#endif #endif
WriteProperty(writer, IntermediateDumpKey::kThreadState, &thread_state);
WriteProperty(writer, IntermediateDumpKey::kFloatState, &float_state);
CaptureMemoryPointedToByThreadState(writer, thread_state);
// Thread ID. // Thread ID.
thread_identifier_info identifier_info; thread_identifier_info identifier_info;

View File

@ -149,6 +149,33 @@ bool ExceptionSnapshotIOSIntermediateDump::InitializeFromSignal(
GetDataValueFromMap(exception_data, Key::kSignalCode, &code); GetDataValueFromMap(exception_data, Key::kSignalCode, &code);
codes_.push_back(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<uint8_t>& bytes = region_data->bytes();
vm_size_t data_size = bytes.size();
if (data_size == 0)
continue;
const vm_address_t data =
reinterpret_cast<const vm_address_t>(bytes.data());
auto memory =
std::make_unique<internal::MemorySnapshotIOSIntermediateDump>();
memory->Initialize(address, data, data_size);
extra_memory_.push_back(std::move(memory));
}
}
}
INITIALIZATION_STATE_SET_VALID(initialized_); INITIALIZATION_STATE_SET_VALID(initialized_);
return true; return true;
} }
@ -281,8 +308,11 @@ const std::vector<uint64_t>& ExceptionSnapshotIOSIntermediateDump::Codes()
std::vector<const MemorySnapshot*> std::vector<const MemorySnapshot*>
ExceptionSnapshotIOSIntermediateDump::ExtraMemory() const { ExceptionSnapshotIOSIntermediateDump::ExtraMemory() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_); std::vector<const MemorySnapshot*> extra_memory;
return std::vector<const MemorySnapshot*>(); for (const auto& memory : extra_memory_) {
extra_memory.push_back(memory.get());
}
return extra_memory;
} }
void ExceptionSnapshotIOSIntermediateDump::LoadContextFromThread( void ExceptionSnapshotIOSIntermediateDump::LoadContextFromThread(

View File

@ -23,6 +23,7 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "snapshot/cpu_context.h" #include "snapshot/cpu_context.h"
#include "snapshot/exception_snapshot.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/ios/ios_intermediate_dump_map.h"
#include "util/mach/mach_extensions.h" #include "util/mach/mach_extensions.h"
#include "util/misc/initialization_state_dcheck.h" #include "util/misc/initialization_state_dcheck.h"
@ -106,6 +107,8 @@ class ExceptionSnapshotIOSIntermediateDump final : public ExceptionSnapshot {
uintptr_t exception_address_; uintptr_t exception_address_;
uint32_t exception_; uint32_t exception_;
uint32_t exception_info_; uint32_t exception_info_;
std::vector<std::unique_ptr<internal::MemorySnapshotIOSIntermediateDump>>
extra_memory_;
InitializationStateDcheck initialized_; InitializationStateDcheck initialized_;
}; };

View File

@ -577,6 +577,18 @@ TEST_F(ProcessSnapshotIOSIntermediateDumpTest, EmptySignalDump) {
IOSIntermediateDumpWriter::ScopedMap map(writer(), Key::kSignalException); IOSIntermediateDumpWriter::ScopedMap map(writer(), Key::kSignalException);
uint64_t thread_id = 1; uint64_t thread_id = 1;
EXPECT_TRUE(writer()->AddProperty(Key::kThreadID, &thread_id)); 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(), IOSIntermediateDumpWriter::ScopedArray threadArray(writer(),
@ -589,6 +601,12 @@ TEST_F(ProcessSnapshotIOSIntermediateDumpTest, EmptySignalDump) {
CloseWriter(); CloseWriter();
ProcessSnapshotIOSIntermediateDump process_snapshot; ProcessSnapshotIOSIntermediateDump process_snapshot;
ASSERT_TRUE(process_snapshot.InitializeWithFilePath(path(), annotations())); 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_FALSE(IsRegularFile(path()));
EXPECT_TRUE(DumpSnapshot(process_snapshot)); EXPECT_TRUE(DumpSnapshot(process_snapshot));
} }