[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] target-arm: add dump-guest-memory support
From: |
Rabin Vincent |
Subject: |
[Qemu-devel] [PATCH] target-arm: add dump-guest-memory support |
Date: |
Wed, 24 Dec 2014 00:29:18 +0100 |
Enable support for the dump-guest-memory command on ARM and AArch64.
The dumped files can be analyzed with crash or similar tools.
Signed-off-by: Rabin Vincent <address@hidden>
---
target-arm/Makefile.objs | 2 +-
target-arm/arch_dump.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++
target-arm/cpu-qom.h | 8 +++
target-arm/cpu.c | 4 ++
4 files changed, 161 insertions(+), 1 deletion(-)
create mode 100644 target-arm/arch_dump.c
diff --git a/target-arm/Makefile.objs b/target-arm/Makefile.objs
index 9460b40..38ba48c 100644
--- a/target-arm/Makefile.objs
+++ b/target-arm/Makefile.objs
@@ -7,6 +7,6 @@ obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
obj-y += translate.o op_helper.o helper.o cpu.o
obj-y += neon_helper.o iwmmxt_helper.o
obj-y += gdbstub.o
-obj-$(CONFIG_SOFTMMU) += psci.o
+obj-$(CONFIG_SOFTMMU) += psci.o arch_dump.o
obj-$(TARGET_AARCH64) += cpu64.o translate-a64.o helper-a64.o gdbstub64.o
obj-y += crypto_helper.o
diff --git a/target-arm/arch_dump.c b/target-arm/arch_dump.c
new file mode 100644
index 0000000..4e7b9a2
--- /dev/null
+++ b/target-arm/arch_dump.c
@@ -0,0 +1,148 @@
+#include "cpu.h"
+
+#include "sysemu/dump.h"
+#include "elf.h"
+
+/* Matches elf_prstatus in <linux/elfcore.h> */
+
+typedef struct {
+ char pad1[24];
+ uint32_t pid;
+ char pad2[44];
+ uint32_t regs[18];
+ char pad3[4];
+} arm_elf_prstatus;
+
+typedef struct {
+ char pad1[32];
+ uint32_t pid;
+ char pad2[76];
+ uint64_t regs[32];
+ uint64_t pc;
+ uint64_t pstate;
+ char pad3[4];
+} aarch64_elf_prstatus;
+
+static size_t round4(size_t size)
+{
+ return ((size + 3) / 4) * 4;
+}
+
+static int write_elf_note(const char *name, uint32_t type,
+ void *desc, size_t descsz,
+ WriteCoreDumpFunction f, void *opaque)
+{
+ size_t note_size, name_size, note_head_size;
+ DumpState *s = opaque;
+ int class = s->dump_info.d_class;
+ Elf64_Nhdr *note64;
+ Elf32_Nhdr *note32;
+ void *note;
+ char *buf;
+ int ret;
+
+ name_size = strlen(name) + 1;
+
+ if (class == ELFCLASS32) {
+ note_head_size = sizeof(Elf32_Nhdr);
+ } else {
+ note_head_size = sizeof(Elf64_Nhdr);
+ }
+
+ note_size = note_head_size + round4(name_size) + descsz;
+ note = g_malloc0(note_size);
+
+ if (class == ELFCLASS32) {
+ note32 = note;
+ note32->n_namesz = cpu_to_dump32(s, name_size);
+ note32->n_descsz = cpu_to_dump32(s, descsz);
+ note32->n_type = cpu_to_dump32(s, type);
+ } else {
+ note64 = note;
+ note64->n_namesz = cpu_to_dump64(s, name_size);
+ note64->n_descsz = cpu_to_dump64(s, descsz);
+ note64->n_type = cpu_to_dump64(s, type);
+ }
+
+ buf = note;
+ buf += note_head_size;
+
+ memcpy(buf, name, name_size);
+ buf += round4(name_size);
+
+ memcpy(buf, desc, descsz);
+
+ ret = f(note, note_size, opaque);
+ g_free(note);
+
+ return ret;
+}
+
+int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque)
+{
+ arm_elf_prstatus prstatus = {.pid = cpuid};
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ memcpy(&(prstatus.regs), cpu->env.regs, sizeof(cpu->env.regs));
+ prstatus.regs[16] = cpsr_read(&cpu->env);
+
+ return write_elf_note("CORE", NT_PRSTATUS,
+ &prstatus, sizeof(prstatus),
+ f, opaque);
+}
+
+int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque)
+{
+ aarch64_elf_prstatus prstatus = {.pid = cpuid};
+ ARMCPU *cpu = ARM_CPU(cs);
+
+ memcpy(&(prstatus.regs), cpu->env.xregs, sizeof(cpu->env.xregs));
+ prstatus.pc = cpu->env.pc;
+ prstatus.pstate = cpu->env.pstate;
+
+ return write_elf_note("CORE", NT_PRSTATUS,
+ &prstatus, sizeof(prstatus),
+ f, opaque);
+}
+
+int arm_cpu_write_elf32_qemunote(WriteCoreDumpFunction f,
+ CPUState *cpu, void *opaque)
+{
+ return 0;
+}
+
+int arm_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
+ CPUState *cpu, void *opaque)
+{
+ return 0;
+}
+
+int cpu_get_dump_info(ArchDumpInfo *info,
+ const struct GuestPhysBlockList *guest_phys_blocks)
+{
+ info->d_machine = ELF_MACHINE;
+ info->d_class = (info->d_machine == EM_ARM) ? ELFCLASS32 : ELFCLASS64;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ info->d_endian = ELFDATA2MSB;
+#else
+ info->d_endian = ELFDATA2LSB;
+#endif
+
+ return 0;
+}
+
+ssize_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+ size_t elf_note_size = round4(sizeof("CORE"));
+
+ if (machine == EM_ARM) {
+ elf_note_size += sizeof(Elf32_Nhdr) + sizeof(arm_elf_prstatus);
+ } else {
+ elf_note_size += sizeof(Elf64_Nhdr) + sizeof(aarch64_elf_prstatus);
+ }
+
+ return elf_note_size * nr_cpus;
+}
diff --git a/target-arm/cpu-qom.h b/target-arm/cpu-qom.h
index ed5a644..7de8ba1 100644
--- a/target-arm/cpu-qom.h
+++ b/target-arm/cpu-qom.h
@@ -205,6 +205,14 @@ bool arm_cpu_exec_interrupt(CPUState *cpu, int int_req);
void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
int flags);
+int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque);
+int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
+ int cpuid, void *opaque);
+int arm_cpu_write_elf32_qemunote(WriteCoreDumpFunction f,
+ CPUState *cpu, void *opaque);
+int arm_cpu_write_elf64_qemunote(WriteCoreDumpFunction f,
+ CPUState *cpu, void *opaque);
hwaddr arm_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
diff --git a/target-arm/cpu.c b/target-arm/cpu.c
index 285947f..679387a 100644
--- a/target-arm/cpu.c
+++ b/target-arm/cpu.c
@@ -1188,6 +1188,10 @@ static void arm_cpu_class_init(ObjectClass *oc, void
*data)
#else
cc->do_interrupt = arm_cpu_do_interrupt;
cc->get_phys_page_debug = arm_cpu_get_phys_page_debug;
+ cc->write_elf32_note = arm_cpu_write_elf32_note;
+ cc->write_elf64_note = arm_cpu_write_elf64_note;
+ cc->write_elf32_qemunote = arm_cpu_write_elf32_qemunote;
+ cc->write_elf64_qemunote = arm_cpu_write_elf64_qemunote;
cc->vmsd = &vmstate_arm_cpu;
#endif
cc->gdb_num_core_regs = 26;
--
2.1.3
- [Qemu-devel] [PATCH] target-arm: add dump-guest-memory support,
Rabin Vincent <=