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::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;

View File

@ -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<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_);
return true;
}
@ -281,8 +308,11 @@ const std::vector<uint64_t>& ExceptionSnapshotIOSIntermediateDump::Codes()
std::vector<const MemorySnapshot*>
ExceptionSnapshotIOSIntermediateDump::ExtraMemory() const {
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
return std::vector<const MemorySnapshot*>();
std::vector<const MemorySnapshot*> extra_memory;
for (const auto& memory : extra_memory_) {
extra_memory.push_back(memory.get());
}
return extra_memory;
}
void ExceptionSnapshotIOSIntermediateDump::LoadContextFromThread(

View File

@ -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<std::unique_ptr<internal::MemorySnapshotIOSIntermediateDump>>
extra_memory_;
InitializationStateDcheck initialized_;
};

View File

@ -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));
}