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
