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

Implement HAVE_ELF_CORE_FPREGS for i386: 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_32.h, which is the legacy FSAVE image without
the trailing software status word that FSAVE does not write either.
cpu_x86_fsave_noinit() produces exactly that, already in target byte
order.

The SSE registers are still absent: the kernel dumps those in a separate
NT_PRXFPREG note, which the generic core dump code has no support for.

Checked with gdb on a core from a program that faults with 1.5 and 2.25
live on the x87 stack: "info float" reads both back, along with the tag
word and the instruction and operand pointers.

Signed-off-by: Matt Turner <[email protected]>
---
 linux-user/i386/elfload.c    |  7 +++++++
 linux-user/i386/target_elf.h | 18 ++++++++++++++++++
 2 files changed, 25 insertions(+)

diff --git ./linux-user/i386/elfload.c ./linux-user/i386/elfload.c
index 2e10f38a41..3c8a65e35c 100644
--- ./linux-user/i386/elfload.c
+++ ./linux-user/i386/elfload.c
@@ -25,6 +25,13 @@ const char *get_elf_platform(CPUState *cs)
     return elf_platform[family - 3];
 }
 
+void elf_core_copy_fpregs(target_elf_fpregset_t *r, const CPUX86State *env)
+{
+    /* The FSAVE image exactly, stored in target byte order. */
+    QEMU_BUILD_BUG_ON(sizeof(*r) != 4 * 7 + 8 * 10);
+    cpu_x86_fsave_noinit((CPUX86State *)env, r, sizeof(*r));
+}
+
 void elf_core_copy_regs(target_elf_gregset_t *r, const CPUX86State *env)
 {
     r->pt.bx = tswapal(env->regs[R_EBX]);
diff --git ./linux-user/i386/target_elf.h ./linux-user/i386/target_elf.h
index eafac8f382..931ea23ffa 100644
--- ./linux-user/i386/target_elf.h
+++ ./linux-user/i386/target_elf.h
@@ -27,6 +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_32.h.  This is the legacy FSAVE image without
+ * the trailing software status word, which FSAVE does not write either.
+ */
+#define HAVE_ELF_CORE_FPREGS    1
+
+typedef struct target_elf_fpregset_t {
+    uint32_t cwd;             /* FPU control word                 */
+    uint32_t swd;             /* FPU status word                  */
+    uint32_t twd;             /* FPU tag word                     */
+    uint32_t fip;             /* FPU IP offset                    */
+    uint32_t fcs;             /* FPU IP selector                  */
+    uint32_t foo;             /* FPU operand pointer offset       */
+    uint32_t fos;             /* FPU operand pointer selector     */
+    uint32_t st_space[20];    /* 8 * 10 bytes for st0-st7         */
+} target_elf_fpregset_t;
+
 /*
  * This is used to ensure we don't load something for the wrong architecture.
  */
-- 
2.54.0


Reply via email to