target-arm: dump-guest-memory: add vfp notes for arm

gdb won't actually dump these with 'info all-registers' since
it first tries to confirm that it should by checking the VFP
hwcap in the .auxv note. Well, we don't generate an .auxv note.

Signed-off-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 1452542185-10914-9-git-send-email-drjones@redhat.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Andrew Jones 2016-01-11 20:56:25 +01:00 committed by Peter Maydell
parent 7d68e47f12
commit ade0d0c0d3
1 changed files with 46 additions and 3 deletions

View File

@ -183,15 +183,28 @@ struct arm_elf_prstatus {
QEMU_BUILD_BUG_ON(sizeof(struct arm_elf_prstatus) != 148);
/* struct user_vfp from arch/arm/include/asm/user.h */
struct arm_user_vfp_state {
uint64_t vregs[32];
uint32_t fpscr;
} QEMU_PACKED;
QEMU_BUILD_BUG_ON(sizeof(struct arm_user_vfp_state) != 260);
struct arm_note {
Elf32_Nhdr hdr;
char name[8]; /* align_up(sizeof("CORE"), 4) */
struct arm_elf_prstatus prstatus;
char name[8]; /* align_up(sizeof("LINUX"), 4) */
union {
struct arm_elf_prstatus prstatus;
struct arm_user_vfp_state vfp;
};
} QEMU_PACKED;
#define ARM_NOTE_HEADER_SIZE offsetof(struct arm_note, prstatus)
#define ARM_PRSTATUS_NOTE_SIZE \
(ARM_NOTE_HEADER_SIZE + sizeof(struct arm_elf_prstatus))
#define ARM_VFP_NOTE_SIZE \
(ARM_NOTE_HEADER_SIZE + sizeof(struct arm_user_vfp_state))
static void arm_note_init(struct arm_note *note, DumpState *s,
const char *name, Elf32_Word namesz,
@ -206,17 +219,40 @@ static void arm_note_init(struct arm_note *note, DumpState *s,
memcpy(note->name, name, namesz);
}
static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env,
int cpuid, DumpState *s)
{
struct arm_note note;
int ret, i;
arm_note_init(&note, s, "LINUX", 6, NT_ARM_VFP, sizeof(note.vfp));
for (i = 0; i < 32; ++i) {
note.vfp.vregs[i] = cpu_to_dump64(s, float64_val(env->vfp.regs[i]));
}
note.vfp.fpscr = cpu_to_dump32(s, vfp_get_fpscr(env));
ret = f(&note, ARM_VFP_NOTE_SIZE, s);
if (ret < 0) {
return -1;
}
return 0;
}
int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque)
{
struct arm_note note;
CPUARMState *env = &ARM_CPU(cs)->env;
DumpState *s = opaque;
int ret, i;
int ret, i, fpvalid = !!arm_feature(env, ARM_FEATURE_VFP);
arm_note_init(&note, s, "CORE", 5, NT_PRSTATUS, sizeof(note.prstatus));
note.prstatus.pr_pid = cpu_to_dump32(s, cpuid);
note.prstatus.pr_fpvalid = cpu_to_dump32(s, fpvalid);
for (i = 0; i < 16; ++i) {
note.prstatus.pr_reg.regs[i] = cpu_to_dump32(s, env->regs[i]);
@ -226,6 +262,8 @@ int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
ret = f(&note, ARM_PRSTATUS_NOTE_SIZE, s);
if (ret < 0) {
return -1;
} else if (fpvalid) {
return arm_write_elf32_vfp(f, env, cpuid, s);
}
return 0;
@ -280,6 +318,8 @@ int cpu_get_dump_info(ArchDumpInfo *info,
ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
{
ARMCPU *cpu = ARM_CPU(first_cpu);
CPUARMState *env = &cpu->env;
size_t note_size;
if (class == ELFCLASS64) {
@ -287,6 +327,9 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
note_size += AARCH64_PRFPREG_NOTE_SIZE;
} else {
note_size = ARM_PRSTATUS_NOTE_SIZE;
if (arm_feature(env, ARM_FEATURE_VFP)) {
note_size += ARM_VFP_NOTE_SIZE;
}
}
return note_size * nr_cpus;