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: If174ff364450ea0265adc522c237b07660332f17
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>
GitOrigin-RevId: 1cea0473a5a1f3124f0d3a95643c573296a2bac5
diff --git a/client/ios_handler/in_process_intermediate_dump_handler.cc b/client/ios_handler/in_process_intermediate_dump_handler.cc
index 6cc6360..29e26cb 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 @@
   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 e347845..9f1852a 100644
--- a/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc
+++ b/snapshot/ios/exception_snapshot_ios_intermediate_dump.cc
@@ -149,6 +149,33 @@
   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 @@
 
 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(
diff --git a/snapshot/ios/exception_snapshot_ios_intermediate_dump.h b/snapshot/ios/exception_snapshot_ios_intermediate_dump.h
index 90966df..dc9d595 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 @@
   uintptr_t exception_address_;
   uint32_t exception_;
   uint32_t exception_info_;
+  std::vector<std::unique_ptr<internal::MemorySnapshotIOSIntermediateDump>>
+      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 29d26a8..69cb43e 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 @@
       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 @@
   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));
 }