A guest core carried only the general-purpose registers, so a debugger
opening one reported the x87 stack and every SSE register as
unavailable.

Implement HAVE_ELF_CORE_FPREGS for x86_64: define target_elf_fpregset_t
to match the kernel's elf_fpregset_t, i.e. struct user_i387_struct from
arch/x86/include/asm/user_64.h, which is the 512 byte FXSAVE image, and
fill it with the existing cpu_x86_fxsave(). As on the signal path, the
helper writes in target byte order, so there is nothing to swap.

QEMU's FXSAVE writes zero for the instruction and operand pointers and
never writes the opcode field, as it does everywhere else, so those
three fields are not recovered from a core.

Checked with gdb on a core from a program that faults with live values
on the x87 stack and in xmm0 and xmm1: "info float" reads back the stack
and the tag word, and the xmm registers and $mxcsr read correctly.

Signed-off-by: Matt Turner <[email protected]>
---
 linux-user/x86_64/elfload.c    | 11 +++++++++++
 linux-user/x86_64/target_elf.h | 20 ++++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git ./linux-user/x86_64/elfload.c ./linux-user/x86_64/elfload.c
index 121a8167ac..4560106faf 100644
--- ./linux-user/x86_64/elfload.c
+++ ./linux-user/x86_64/elfload.c
@@ -42,6 +42,17 @@ bool init_guest_commpage(void)
     return true;
 }
 
+void elf_core_copy_fpregs(target_elf_fpregset_t *r, const CPUX86State *env)
+{
+    QEMU_BUILD_BUG_ON(sizeof(*r) != sizeof(X86LegacyXSaveArea));
+    /*
+     * The helper stores the image in target byte order.  cpu_x86_fxsave()
+     * folds the softfloat exception flags back into env->mxcsr, so the
+     * const has to go.
+     */
+    cpu_x86_fxsave((CPUX86State *)env, r, sizeof(*r));
+}
+
 void elf_core_copy_regs(target_elf_gregset_t *r, const CPUX86State *env)
 {
     r->pt.r15 = tswapal(env->regs[15]);
diff --git ./linux-user/x86_64/target_elf.h ./linux-user/x86_64/target_elf.h
index 840bddf5ec..23f84f6a91 100644
--- ./linux-user/x86_64/target_elf.h
+++ ./linux-user/x86_64/target_elf.h
@@ -27,4 +27,24 @@ typedef struct target_elf_gregset_t {
     struct target_user_regs_struct pt;
 } target_elf_gregset_t;
 
+/*
+ * Matches the kernel's elf_fpregset_t, i.e. struct user_i387_struct from
+ * arch/x86/include/asm/user_64.h, which is the 512 byte FXSAVE image.
+ */
+#define HAVE_ELF_CORE_FPREGS    1
+
+typedef struct target_elf_fpregset_t {
+    uint16_t cwd;             /* FPU control word                   */
+    uint16_t swd;             /* FPU status word                    */
+    uint16_t twd;             /* abridged tag word, not the x87 one */
+    uint16_t fop;             /* last instruction opcode            */
+    uint64_t rip;             /* instruction pointer                */
+    uint64_t rdp;             /* data pointer                       */
+    uint32_t mxcsr;
+    uint32_t mxcsr_mask;
+    uint32_t st_space[32];    /*  8 * 16 bytes for st0-st7          */
+    uint32_t xmm_space[64];   /* 16 * 16 bytes for xmm0-xmm15       */
+    uint32_t padding[24];
+} target_elf_fpregset_t;
+
 #endif
-- 
2.54.0


Reply via email to