[fuchsia][arm64] support vector registers

Bug: fuchsia:DX-642
Change-Id: I898b75e47d0dd810025db6ea27e2e0e73ec82768
Tested: CQ
Reviewed-on: https://chromium-review.googlesource.com/c/1310513
Commit-Queue: Francois Rousseau <frousseau@google.com>
Reviewed-by: Scott Graham <scottmg@chromium.org>
diff --git a/snapshot/fuchsia/cpu_context_fuchsia.cc b/snapshot/fuchsia/cpu_context_fuchsia.cc
index f4e3be6..226bfc6 100644
--- a/snapshot/fuchsia/cpu_context_fuchsia.cc
+++ b/snapshot/fuchsia/cpu_context_fuchsia.cc
@@ -47,8 +47,9 @@
 
 #elif defined(ARCH_CPU_ARM64)
 
-void InitializeCPUContextARM64_NoFloatingPoint(
+void InitializeCPUContextARM64(
     const zx_thread_state_general_regs_t& thread_context,
+    const zx_thread_state_vector_regs_t& vector_context,
     CPUContextARM64* context) {
   memset(context, 0, sizeof(*context));
 
@@ -80,6 +81,12 @@
   }
   context->spsr =
       static_cast<decltype(context->spsr)>(thread_context.cpsr) & kNZCV;
+
+  context->fpcr = vector_context.fpcr;
+  context->fpsr = vector_context.fpsr;
+  static_assert(sizeof(context->fpsimd) == sizeof(vector_context.v),
+                "registers size mismatch");
+  memcpy(&context->fpsimd, &vector_context.v, sizeof(vector_context.v));
 }
 
 #endif  // ARCH_CPU_X86_64
diff --git a/snapshot/fuchsia/cpu_context_fuchsia.h b/snapshot/fuchsia/cpu_context_fuchsia.h
index d81a322..9227bfc 100644
--- a/snapshot/fuchsia/cpu_context_fuchsia.h
+++ b/snapshot/fuchsia/cpu_context_fuchsia.h
@@ -45,12 +45,13 @@
 //! \brief Initializes a CPUContextARM64 structure from native context
 //!     structures on Fuchsia.
 //!
-//! Floating point registers are currently initialized to zero.
-//!
 //! \param[in] thread_context The native thread context.
+//! \param[in] vector_context The native vector context that also contains the
+//!                           floating point registers.
 //! \param[out] context The CPUContextARM64 structure to initialize.
-void InitializeCPUContextARM64_NoFloatingPoint(
+void InitializeCPUContextARM64(
     const zx_thread_state_general_regs_t& thread_context,
+    const zx_thread_state_vector_regs_t& vector_context,
     CPUContextARM64* context);
 
 #endif  // ARCH_CPU_ARM64 || DOXYGEN
diff --git a/snapshot/fuchsia/exception_snapshot_fuchsia.cc b/snapshot/fuchsia/exception_snapshot_fuchsia.cc
index 0bd08bb..f70b966 100644
--- a/snapshot/fuchsia/exception_snapshot_fuchsia.cc
+++ b/snapshot/fuchsia/exception_snapshot_fuchsia.cc
@@ -65,9 +65,8 @@
 #elif defined(ARCH_CPU_ARM64)
       context_.architecture = kCPUArchitectureARM64;
       context_.arm64 = &context_arch_;
-      // TODO(fuchsia/DX-642): Add float context once saved in |t|.
-      InitializeCPUContextARM64_NoFloatingPoint(t.general_registers,
-                                                context_.arm64);
+      InitializeCPUContextARM64(
+          t.general_registers, t.vector_registers, context_.arm64);
 #else
 #error Port.
 #endif
diff --git a/snapshot/fuchsia/process_reader_fuchsia.cc b/snapshot/fuchsia/process_reader_fuchsia.cc
index 4012301..e60766a 100644
--- a/snapshot/fuchsia/process_reader_fuchsia.cc
+++ b/snapshot/fuchsia/process_reader_fuchsia.cc
@@ -276,15 +276,26 @@
         thread.state = thread_info.state;
       }
 
-      zx_thread_state_general_regs_t regs;
+      zx_thread_state_general_regs_t general_regs;
       status = thread_handles[i].read_state(
-          ZX_THREAD_STATE_GENERAL_REGS, &regs, sizeof(regs));
+          ZX_THREAD_STATE_GENERAL_REGS, &general_regs, sizeof(general_regs));
       if (status != ZX_OK) {
-        ZX_LOG(WARNING, status) << "zx_thread_read_state";
+        ZX_LOG(WARNING, status)
+            << "zx_thread_read_state(ZX_THREAD_STATE_GENERAL_REGS)";
       } else {
-        thread.general_registers = regs;
+        thread.general_registers = general_regs;
 
-        GetStackRegions(regs, memory_map_, &thread.stack_regions);
+        GetStackRegions(general_regs, memory_map_, &thread.stack_regions);
+      }
+
+      zx_thread_state_vector_regs_t vector_regs;
+      status = thread_handles[i].read_state(
+          ZX_THREAD_STATE_VECTOR_REGS, &vector_regs, sizeof(vector_regs));
+      if (status != ZX_OK) {
+        ZX_LOG(WARNING, status)
+            << "zx_thread_read_state(ZX_THREAD_STATE_VECTOR_REGS)";
+      } else {
+        thread.vector_registers = vector_regs;
       }
     }
 
diff --git a/snapshot/fuchsia/process_reader_fuchsia.h b/snapshot/fuchsia/process_reader_fuchsia.h
index 6a6a650..28a1e93 100644
--- a/snapshot/fuchsia/process_reader_fuchsia.h
+++ b/snapshot/fuchsia/process_reader_fuchsia.h
@@ -77,6 +77,10 @@
     //!     returned by `zx_thread_read_state()`.
     zx_thread_state_general_regs_t general_registers = {};
 
+    //! \brief The raw architecture-specific `zx_thread_state_vector_regs_t` as
+    //!     returned by `zx_thread_read_state()`.
+    zx_thread_state_vector_regs_t vector_registers = {};
+
     //! \brief The regions representing the stack. The first entry in the vector
     //!     represents the callstack, and further entries optionally identify
     //!     other stack data when the thread uses a split stack representation.
diff --git a/snapshot/fuchsia/thread_snapshot_fuchsia.cc b/snapshot/fuchsia/thread_snapshot_fuchsia.cc
index 1cc09af..b3a4cec 100644
--- a/snapshot/fuchsia/thread_snapshot_fuchsia.cc
+++ b/snapshot/fuchsia/thread_snapshot_fuchsia.cc
@@ -45,9 +45,8 @@
 #elif defined(ARCH_CPU_ARM64)
   context_.architecture = kCPUArchitectureARM64;
   context_.arm64 = &context_arch_;
-  // TODO(fuchsia/DX-642): Add float context once saved in |thread|.
-  InitializeCPUContextARM64_NoFloatingPoint(thread.general_registers,
-                                            context_.arm64);
+  InitializeCPUContextARM64(
+      thread.general_registers, thread.vector_registers, context_.arm64);
 #else
 #error Port.
 #endif