diff --git a/snapshot/fuchsia/cpu_context_fuchsia.cc b/snapshot/fuchsia/cpu_context_fuchsia.cc index 8c907cb9..9730a0a7 100644 --- a/snapshot/fuchsia/cpu_context_fuchsia.cc +++ b/snapshot/fuchsia/cpu_context_fuchsia.cc @@ -21,8 +21,9 @@ namespace internal { #if defined(ARCH_CPU_X86_64) -void InitializeCPUContextX86_64_NoFloatingPoint( +void InitializeCPUContextX86_64( const zx_thread_state_general_regs_t& thread_context, + const zx_thread_state_fp_regs_t& float_context, CPUContextX86_64* context) { memset(context, 0, sizeof(*context)); context->rax = thread_context.rax; @@ -43,6 +44,19 @@ void InitializeCPUContextX86_64_NoFloatingPoint( context->r15 = thread_context.r15; context->rip = thread_context.rip; context->rflags = thread_context.rflags; + + context->fxsave.fcw = float_context.fcw; + context->fxsave.fsw = float_context.fsw; + context->fxsave.ftw = float_context.ftw; + context->fxsave.fop = float_context.fop; + context->fxsave.fpu_ip_64 = float_context.fip; + context->fxsave.fpu_dp_64 = float_context.fdp; + + for (size_t i = 0; i < std::size(float_context.st); ++i) { + memcpy(&context->fxsave.st_mm[i], + &float_context.st[i], + sizeof(float_context.st[i])); + } } #elif defined(ARCH_CPU_ARM64) diff --git a/snapshot/fuchsia/cpu_context_fuchsia.h b/snapshot/fuchsia/cpu_context_fuchsia.h index 3cce60ed..99bfa6f9 100644 --- a/snapshot/fuchsia/cpu_context_fuchsia.h +++ b/snapshot/fuchsia/cpu_context_fuchsia.h @@ -29,13 +29,14 @@ namespace internal { //! \brief Initializes a CPUContextX86_64 structure from native context //! structures on Fuchsia. //! -//! Floating point registers are currently initialized to zero. //! Segment registers are currently initialized to zero. //! //! \param[in] thread_context The native thread context. +//! \param[in] float_context The native floating point context. //! \param[out] context The CPUContextX86_64 structure to initialize. -void InitializeCPUContextX86_64_NoFloatingPoint( +void InitializeCPUContextX86_64( const zx_thread_state_general_regs_t& thread_context, + const zx_thread_state_fp_regs_t& float_context, CPUContextX86_64* context); #endif // ARCH_CPU_X86_64 || DOXYGEN diff --git a/snapshot/fuchsia/exception_snapshot_fuchsia.cc b/snapshot/fuchsia/exception_snapshot_fuchsia.cc index 50ea6fff..017a6c67 100644 --- a/snapshot/fuchsia/exception_snapshot_fuchsia.cc +++ b/snapshot/fuchsia/exception_snapshot_fuchsia.cc @@ -70,9 +70,9 @@ bool ExceptionSnapshotFuchsia::Initialize( #if defined(ARCH_CPU_X86_64) context_.architecture = kCPUArchitectureX86_64; context_.x86_64 = &context_arch_; - // TODO(fxbug.dev/5496): Add float context once saved in |t|. - InitializeCPUContextX86_64_NoFloatingPoint(t->general_registers, - context_.x86_64); + // TODO(fxbug.dev/5496): Add vector context. + InitializeCPUContextX86_64( + t->general_registers, t->fp_registers, context_.x86_64); #elif defined(ARCH_CPU_ARM64) context_.architecture = kCPUArchitectureARM64; context_.arm64 = &context_arch_; diff --git a/snapshot/fuchsia/process_reader_fuchsia.cc b/snapshot/fuchsia/process_reader_fuchsia.cc index 02be7c29..06f4c2e4 100644 --- a/snapshot/fuchsia/process_reader_fuchsia.cc +++ b/snapshot/fuchsia/process_reader_fuchsia.cc @@ -346,6 +346,16 @@ void ProcessReaderFuchsia::InitializeThreads() { } } + zx_thread_state_fp_regs_t fp_regs; + status = thread_handles[i].read_state( + ZX_THREAD_STATE_FP_REGS, &fp_regs, sizeof(fp_regs)); + if (status != ZX_OK) { + ZX_LOG(WARNING, status) + << "zx_thread_read_state(ZX_THREAD_STATE_FP_REGS)"; + } else { + thread.fp_registers = fp_regs; + } + zx_thread_state_vector_regs_t vector_regs; status = thread_handles[i].read_state( ZX_THREAD_STATE_VECTOR_REGS, &vector_regs, sizeof(vector_regs)); diff --git a/snapshot/fuchsia/process_reader_fuchsia.h b/snapshot/fuchsia/process_reader_fuchsia.h index cfeb6781..31e78869 100644 --- a/snapshot/fuchsia/process_reader_fuchsia.h +++ b/snapshot/fuchsia/process_reader_fuchsia.h @@ -76,6 +76,10 @@ class ProcessReaderFuchsia { //! returned by `zx_thread_read_state()`. zx_thread_state_general_regs_t general_registers = {}; + //! \brief The raw architecture-specific `zx_thread_state_fp_regs_t` as + //! returned by `zx_thread_read_state()`. + zx_thread_state_fp_regs_t fp_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 = {}; diff --git a/snapshot/fuchsia/thread_snapshot_fuchsia.cc b/snapshot/fuchsia/thread_snapshot_fuchsia.cc index 20b85dde..0681ca27 100644 --- a/snapshot/fuchsia/thread_snapshot_fuchsia.cc +++ b/snapshot/fuchsia/thread_snapshot_fuchsia.cc @@ -40,9 +40,9 @@ bool ThreadSnapshotFuchsia::Initialize( #if defined(ARCH_CPU_X86_64) context_.architecture = kCPUArchitectureX86_64; context_.x86_64 = &context_arch_; - // TODO(fuchsia/DX-642): Add float context once saved in |thread|. - InitializeCPUContextX86_64_NoFloatingPoint(thread.general_registers, - context_.x86_64); + // TODO(fxbug.dev/5496): Add vector context. + InitializeCPUContextX86_64( + thread.general_registers, thread.fp_registers, context_.x86_64); #elif defined(ARCH_CPU_ARM64) context_.architecture = kCPUArchitectureARM64; context_.arm64 = &context_arch_;