The command's usage:
dump [-p] protocol [begin] [length]
The supported protocol can be file or fd:
1. file: the protocol starts with "file:", and the following string is
the file's path.
2. fd: the protocol starts with "fd:", and the following string is the
fd's name.
Note:
1. If you want to use gdb to process the core, please specify -p option.
The reason why the -p option is not default is:
a. guest machine in a catastrophic state can have corrupted memory,
which we cannot trust.
b. The guest machine can be in read-mode even if paging is enabled.
For example: the guest machine uses ACPI to sleep, and ACPI sleep
state goes in real-mode.
2. This command doesn't support the fd that is is associated with a pipe,
socket, or FIFO(lseek will fail with such fd).
3. If you don't want to dump all guest's memory, please specify the start
physical address and the length.
Signed-off-by: Wen Congyang
---
Makefile.target |2 +-
dump.c | 827 ++
elf.h|5 +
hmp-commands.hx | 28 ++
hmp.c| 22 ++
hmp.h|1 +
memory_mapping.c | 27 ++
memory_mapping.h |3 +
qapi-schema.json | 34 +++
qmp-commands.hx | 38 +++
10 files changed, 986 insertions(+), 1 deletions(-)
create mode 100644 dump.c
diff --git a/Makefile.target b/Makefile.target
index 2e20ed2..43004bc 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -222,7 +222,7 @@ obj-$(CONFIG_NO_KVM) += kvm-stub.o
obj-$(CONFIG_VGA) += vga.o
obj-y += memory.o savevm.o
obj-y += memory_mapping.o
-obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o
+obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o dump.o
LIBS+=-lz
obj-i386-$(CONFIG_KVM) += hyperv.o
diff --git a/dump.c b/dump.c
new file mode 100644
index 000..d1b3933
--- /dev/null
+++ b/dump.c
@@ -0,0 +1,827 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ * Wen Congyang
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include
+#include "elf.h"
+#include
+#include
+#include "cpu.h"
+#include "cpu-all.h"
+#include "targphys.h"
+#include "monitor.h"
+#include "kvm.h"
+#include "dump.h"
+#include "sysemu.h"
+#include "bswap.h"
+#include "memory_mapping.h"
+#include "error.h"
+#include "qmp-commands.h"
+#include "gdbstub.h"
+
+static uint16_t cpu_convert_to_target16(uint16_t val, int endian)
+{
+if (endian == ELFDATA2LSB) {
+val = cpu_to_le16(val);
+} else {
+val = cpu_to_be16(val);
+}
+
+return val;
+}
+
+static uint32_t cpu_convert_to_target32(uint32_t val, int endian)
+{
+if (endian == ELFDATA2LSB) {
+val = cpu_to_le32(val);
+} else {
+val = cpu_to_be32(val);
+}
+
+return val;
+}
+
+static uint64_t cpu_convert_to_target64(uint64_t val, int endian)
+{
+if (endian == ELFDATA2LSB) {
+val = cpu_to_le64(val);
+} else {
+val = cpu_to_be64(val);
+}
+
+return val;
+}
+
+typedef struct DumpState {
+ArchDumpInfo dump_info;
+MemoryMappingList list;
+uint16_t phdr_num;
+uint32_t sh_info;
+bool have_section;
+bool resume;
+target_phys_addr_t memory_offset;
+int fd;
+
+RAMBlock *block;
+ram_addr_t start;
+bool has_filter;
+int64_t begin;
+int64_t length;
+Error **errp;
+} DumpState;
+
+static int dump_cleanup(DumpState *s)
+{
+int ret = 0;
+
+memory_mapping_list_free(&s->list);
+if (s->fd != -1) {
+close(s->fd);
+}
+if (s->resume) {
+vm_start();
+}
+
+return ret;
+}
+
+static void dump_error(DumpState *s, const char *reason)
+{
+dump_cleanup(s);
+}
+
+static int fd_write_vmcore(target_phys_addr_t offset, void *buf, size_t size,
+ void *opaque)
+{
+DumpState *s = opaque;
+int fd = s->fd;
+off_t ret;
+size_t writen_size;
+
+while (1) {
+ret = lseek(fd, offset, SEEK_SET);
+if (ret < 0) {
+if (errno == ESPIPE) {
+error_set(s->errp, QERR_PIPE_OR_SOCKET_FD);
+return -1;
+}
+
+if (errno != EINTR && errno != EAGAIN) {
+return -1;
+}
+continue;
+}
+break;
+}
+
+/* The fd may be passed from user, and it can be non-blocked */
+while (size) {
+writen_size = qemu_write_full(fd, buf, size);
+if (writen_size != size && errno != EAGAIN) {
+return -1;
+}
+
+buf += writen_size;
+size -= writen_size;
+}
+
+return 0;
+}
+
+static int write_elf64_header(DumpState *s)
+{
+Elf64_Ehdr elf_header;
+int ret;
+int endian = s->dump_info.d_endian;
+
+memset(&elf_header, 0, sizeof(Elf64_Ehdr));
+memcpy(&elf_header, ELFMAG, SELFMAG);
+elf_header.e_