[Qemu-devel] [PATCH 12/12 v11] introduce a new monitor command 'dump-guest-memory' to dump guest's memory

2012-03-26 Thread Wen Congyang
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_

Re: [Qemu-devel] [PATCH 12/12 v11] introduce a new monitor command 'dump-guest-memory' to dump guest's memory

2012-04-01 Thread Wen Congyang
At 03/26/2012 06:06 PM, Wen Congyang Wrote:
> 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



> +/* write the memroy to vmcore. 1 page per I/O. */
> +static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
> +target_phys_addr_t *offset, int64_t size)
> +{
> +int i, ret;

The type of i should be int64_t. Otherwise,  i * TARGET_PAGE_SIZE
may be overflow.

I will resend this patch.

Thanks
Wen Congyang

> +
> +for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
> +ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
> + TARGET_PAGE_SIZE, offset);
> +if (ret < 0) {
> +return ret;
> +}
> +}
> +
> +if ((size % TARGET_PAGE_SIZE) != 0) {
> +ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
> + size % TARGET_PAGE_SIZE, offset);
> +if (ret < 0) {
> +return ret;
> +}
> +}
> +
> +return 0;
> +}
> +