Re: [PATCH] add support to "virsh dump-guest-memory"(qemu memory dump)

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



At 2012-8-8 21:26, Dave Anderson wrote:


----- Original Message -----
At 2012-8-8 2:59, Dave Anderson wrote:

  >
  >  Anyway, it was surprising to note is that the two dumpfiles can already
  >  can be read with no problem by the crash utility -- with no additional
  >  patches to support it.  The crash utility just thinks that it's a kdump
  >  with some unknown "QEMU" ELF notes:

That's right. The formats are extremely similar, except the qemu note
section.

  >  I should have suggested moving one of the currently-existing pc->flags bits into
  >  pc->flags2, and keeping all the dumpfile types in pc->flags.  Or at least create a

I think it's a better choice. But encountering a new type of dump file,
creating a patch used to move bits in pc->flags can easily put things
into a mess. Why not use a new flag only used to keep dumpfile types?

Yes, that's probably a better idea.  When the next "real" dumpfile type
comes along, perhaps we can go that route.

I see. And I reworked the patches to treat qemu memory dump as kdump.

  >  But -- it seems that we can just leave the dumpfile type as a "KDUMP_ELF32/KDUMP_ELF64",
  >  and then based upon the existence of a "QEMU" note, just set a QEMU_MEM_DUMP pc->flags2
  >  bit that can be used everywhere that you're interested in accessing the "QEMU"
  >  notes/registers section?  Wouldn't that be far simpler?

Treat it as a kdump files seems cool to me. The only problem is I still
need to distinguish kdump and qemu memory dump, not only using qemu note
section, but also the first 640K is special(when doing qemu memory dump,
the second kernel is working).

Right, and you will be able to set the new QEMU_MEM_DUMP flag very early
on during the dumpfile determination phase so that later you will have
that knowledge at hand later on when you want to deal with the notes.

With respect to the "second-kernel" issue, I would presume that you would
have to use the currently-existing "--machdep phys_base=<physaddr>" capability
for x86_64?

Yes, that's right. To see dump image from the 2nd kernel's view,
phys_base should be set.

P.S.
I will suspend the work for about one week because of personal affairs.


Dave

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility




--
--
Regards
Qiao Nuohan


>From a11545d9d273e115bdf257bb9e94709146b99727 Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@xxxxxxxxxxxxxx>
Date: Sun, 22 Jul 2012 10:24:58 +0800
Subject: [PATCH 3/3] display registers stored in qemu note section

---
 netdump.c |  210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 netdump.h |   22 +++++++
 2 files changed, 232 insertions(+), 0 deletions(-)

diff --git a/netdump.c b/netdump.c
index e3cc1ce..235bced 100644
--- a/netdump.c
+++ b/netdump.c
@@ -1690,12 +1690,14 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
 	char *ptr;
 	ulong *uptr;
 	int xen_core, vmcoreinfo, eraseinfo;
+	int qemu_info;
 	uint64_t remaining, notesize;
 
 	note = (Elf32_Nhdr *)((char *)nd->elf32 + offset);
 
         BZERO(buf, BUFSIZE);
 	xen_core = vmcoreinfo = eraseinfo = FALSE;
+	qemu_info = FALSE;
         ptr = (char *)note + sizeof(Elf32_Nhdr);
 
 	if (ptr > (nd->elf_header + nd->header_size)) {
@@ -1786,6 +1788,7 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
 		xen_core = STRNEQ(buf, "XEN CORE") || STRNEQ(buf, "Xen");
 		vmcoreinfo = STRNEQ(buf, "VMCOREINFO");
 		eraseinfo = STRNEQ(buf, "ERASEINFO");
+		qemu_info = STRNEQ(buf, "QEMU");
 		if (xen_core) {
 			netdump_print("(unknown Xen n_type)\n"); 
 			if (store)
@@ -1876,6 +1879,103 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
 	if (xen_core)
 		uptr = (ulong *)roundup((ulong)uptr, 4);
 
+	if (CRASHDEBUG(1) & qemu_info) {
+		netdump_print("version:%08lx      size:%08lx\n",
+				((QEMUCPUState *)uptr)->version,
+				((QEMUCPUState *)uptr)->size);
+		netdump_print("rax:%016llx  rbx:%016llx  rcx:%016llx\n",
+				((QEMUCPUState *)uptr)->rax,
+				((QEMUCPUState *)uptr)->rbx,
+				((QEMUCPUState *)uptr)->rcx);
+		netdump_print("rdx:%016llx  rsi:%016llx  rdi:%016llx\n",
+				((QEMUCPUState *)uptr)->rdx,
+				((QEMUCPUState *)uptr)->rsi,
+				((QEMUCPUState *)uptr)->rdi);
+		netdump_print("rsp:%016llx  rbp:%016llx\n",
+				((QEMUCPUState *)uptr)->rsp,
+				((QEMUCPUState *)uptr)->rbp);
+		netdump_print("rip:%016llx  rflags:%016llx\n",
+				((QEMUCPUState *)uptr)->rip,
+				((QEMUCPUState *)uptr)->rflags);
+		netdump_print("cs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->cs.selector,
+				((QEMUCPUState *)uptr)->cs.limit,
+				((QEMUCPUState *)uptr)->cs.flags,
+				((QEMUCPUState *)uptr)->cs.pad,
+				((QEMUCPUState *)uptr)->cs.base);
+		netdump_print("ds:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ds.selector,
+				((QEMUCPUState *)uptr)->ds.limit,
+				((QEMUCPUState *)uptr)->ds.flags,
+				((QEMUCPUState *)uptr)->ds.pad,
+				((QEMUCPUState *)uptr)->ds.base);
+		netdump_print("es:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->es.selector,
+				((QEMUCPUState *)uptr)->es.limit,
+				((QEMUCPUState *)uptr)->es.flags,
+				((QEMUCPUState *)uptr)->es.pad,
+				((QEMUCPUState *)uptr)->es.base);
+		netdump_print("fs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->fs.selector,
+				((QEMUCPUState *)uptr)->fs.limit,
+				((QEMUCPUState *)uptr)->fs.flags,
+				((QEMUCPUState *)uptr)->fs.pad,
+				((QEMUCPUState *)uptr)->fs.base);
+		netdump_print("gs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->gs.selector,
+				((QEMUCPUState *)uptr)->gs.limit,
+				((QEMUCPUState *)uptr)->gs.flags,
+				((QEMUCPUState *)uptr)->gs.pad,
+				((QEMUCPUState *)uptr)->gs.base);
+		netdump_print("ss:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ss.selector,
+				((QEMUCPUState *)uptr)->ss.limit,
+				((QEMUCPUState *)uptr)->ss.flags,
+				((QEMUCPUState *)uptr)->ss.pad,
+				((QEMUCPUState *)uptr)->ss.base);
+		netdump_print("ldt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ldt.selector,
+				((QEMUCPUState *)uptr)->ldt.limit,
+				((QEMUCPUState *)uptr)->ldt.flags,
+				((QEMUCPUState *)uptr)->ldt.pad,
+				((QEMUCPUState *)uptr)->ldt.base);
+		netdump_print("tr:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->tr.selector,
+				((QEMUCPUState *)uptr)->tr.limit,
+				((QEMUCPUState *)uptr)->tr.flags,
+				((QEMUCPUState *)uptr)->tr.pad,
+				((QEMUCPUState *)uptr)->tr.base);
+		netdump_print("gdt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->gdt.selector,
+				((QEMUCPUState *)uptr)->gdt.limit,
+				((QEMUCPUState *)uptr)->gdt.flags,
+				((QEMUCPUState *)uptr)->gdt.pad,
+				((QEMUCPUState *)uptr)->gdt.base);
+		netdump_print("idt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->idt.selector,
+				((QEMUCPUState *)uptr)->idt.limit,
+				((QEMUCPUState *)uptr)->idt.flags,
+				((QEMUCPUState *)uptr)->idt.pad,
+				((QEMUCPUState *)uptr)->idt.base);
+		netdump_print("cr[0]:%016llx  cr[1]:%016llx  cr[2]:%016llx\n",
+				((QEMUCPUState *)uptr)->cr[0],
+				((QEMUCPUState *)uptr)->cr[1],
+				((QEMUCPUState *)uptr)->cr[2]);
+		netdump_print("cr[3]:%016llx  cr[4]:%016llx\n",
+				((QEMUCPUState *)uptr)->cr[3],
+				((QEMUCPUState *)uptr)->cr[4]);
+	}
+
 	if (vmcoreinfo || eraseinfo) {
                 netdump_print("                         ");
                 ptr += note->n_namesz + 1;
@@ -1920,6 +2020,7 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 	int *iptr;
 	ulong *up;
 	int xen_core, vmcoreinfo, eraseinfo;
+	int qemu_info;
 	uint64_t remaining, notesize;
 
 	note = (Elf64_Nhdr *)((char *)nd->elf64 + offset);
@@ -1927,6 +2028,7 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
         BZERO(buf, BUFSIZE);
         ptr = (char *)note + sizeof(Elf64_Nhdr);
 	xen_core = vmcoreinfo = eraseinfo = FALSE;
+	qemu_info = FALSE;
 
 	if (ptr > (nd->elf_header + nd->header_size)) {
 		error(WARNING, 
@@ -2047,6 +2149,7 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 		xen_core = STRNEQ(buf, "XEN CORE") || STRNEQ(buf, "Xen");
 		vmcoreinfo = STRNEQ(buf, "VMCOREINFO");
 		eraseinfo = STRNEQ(buf, "ERASEINFO");
+		qemu_info = STRNEQ(buf, "QEMU");
                 if (xen_core) {
                         netdump_print("(unknown Xen n_type)\n");
 			if (store)
@@ -2149,6 +2252,113 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
 			uptr = (ulonglong *)roundup((ulong)uptr, 4);
 	}
 
+	if (CRASHDEBUG(1) & qemu_info) {
+		netdump_print("version:%08lx      size:%08lx\n",
+				((QEMUCPUState *)uptr)->version,
+				((QEMUCPUState *)uptr)->size);
+		netdump_print("rax:%016llx  rbx:%016llx  rcx:%016llx\n",
+				((QEMUCPUState *)uptr)->rax,
+				((QEMUCPUState *)uptr)->rbx,
+				((QEMUCPUState *)uptr)->rcx);
+		netdump_print("rdx:%016llx  rsi:%016llx  rdi:%016llx\n",
+				((QEMUCPUState *)uptr)->rdx,
+				((QEMUCPUState *)uptr)->rsi,
+				((QEMUCPUState *)uptr)->rdi);
+		netdump_print("rsp:%016llx  rbp:%016llx  r8:%016llx\n",
+				((QEMUCPUState *)uptr)->rsp,
+				((QEMUCPUState *)uptr)->rbp,
+				((QEMUCPUState *)uptr)->r8);
+		netdump_print("r9:%016llx   r10:%016llx  r11:%016llx\n",
+				((QEMUCPUState *)uptr)->r9,
+				((QEMUCPUState *)uptr)->r10,
+				((QEMUCPUState *)uptr)->r11);
+		netdump_print("r12:%016llx  r13:%016llx  r14:%016llx\n",
+				((QEMUCPUState *)uptr)->r12,
+				((QEMUCPUState *)uptr)->r13,
+				((QEMUCPUState *)uptr)->r14);
+		netdump_print("r15:%016llx  rip:%016llx  rflags:%016llx\n",
+				((QEMUCPUState *)uptr)->r15,
+				((QEMUCPUState *)uptr)->rip,
+				((QEMUCPUState *)uptr)->rflags);
+		netdump_print("cs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->cs.selector,
+				((QEMUCPUState *)uptr)->cs.limit,
+				((QEMUCPUState *)uptr)->cs.flags,
+				((QEMUCPUState *)uptr)->cs.pad,
+				((QEMUCPUState *)uptr)->cs.base);
+		netdump_print("ds:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ds.selector,
+				((QEMUCPUState *)uptr)->ds.limit,
+				((QEMUCPUState *)uptr)->ds.flags,
+				((QEMUCPUState *)uptr)->ds.pad,
+				((QEMUCPUState *)uptr)->ds.base);
+		netdump_print("es:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->es.selector,
+				((QEMUCPUState *)uptr)->es.limit,
+				((QEMUCPUState *)uptr)->es.flags,
+				((QEMUCPUState *)uptr)->es.pad,
+				((QEMUCPUState *)uptr)->es.base);
+		netdump_print("fs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->fs.selector,
+				((QEMUCPUState *)uptr)->fs.limit,
+				((QEMUCPUState *)uptr)->fs.flags,
+				((QEMUCPUState *)uptr)->fs.pad,
+				((QEMUCPUState *)uptr)->fs.base);
+		netdump_print("gs:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->gs.selector,
+				((QEMUCPUState *)uptr)->gs.limit,
+				((QEMUCPUState *)uptr)->gs.flags,
+				((QEMUCPUState *)uptr)->gs.pad,
+				((QEMUCPUState *)uptr)->gs.base);
+		netdump_print("ss:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ss.selector,
+				((QEMUCPUState *)uptr)->ss.limit,
+				((QEMUCPUState *)uptr)->ss.flags,
+				((QEMUCPUState *)uptr)->ss.pad,
+				((QEMUCPUState *)uptr)->ss.base);
+		netdump_print("ldt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->ldt.selector,
+				((QEMUCPUState *)uptr)->ldt.limit,
+				((QEMUCPUState *)uptr)->ldt.flags,
+				((QEMUCPUState *)uptr)->ldt.pad,
+				((QEMUCPUState *)uptr)->ldt.base);
+		netdump_print("tr:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->tr.selector,
+				((QEMUCPUState *)uptr)->tr.limit,
+				((QEMUCPUState *)uptr)->tr.flags,
+				((QEMUCPUState *)uptr)->tr.pad,
+				((QEMUCPUState *)uptr)->tr.base);
+		netdump_print("gdt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->gdt.selector,
+				((QEMUCPUState *)uptr)->gdt.limit,
+				((QEMUCPUState *)uptr)->gdt.flags,
+				((QEMUCPUState *)uptr)->gdt.pad,
+				((QEMUCPUState *)uptr)->gdt.base);
+		netdump_print("idt:\n  selector:%08lx  limit:%08lx  flags:%08lx\n\
+  pad:%08lx  base:%016llx\n",
+				((QEMUCPUState *)uptr)->idt.selector,
+				((QEMUCPUState *)uptr)->idt.limit,
+				((QEMUCPUState *)uptr)->idt.flags,
+				((QEMUCPUState *)uptr)->idt.pad,
+				((QEMUCPUState *)uptr)->idt.base);
+		netdump_print("cr[0]:%016llx  cr[1]:%016llx  cr[2]:%016llx\n",
+				((QEMUCPUState *)uptr)->cr[0],
+				((QEMUCPUState *)uptr)->cr[1],
+				((QEMUCPUState *)uptr)->cr[2]);
+		netdump_print("cr[3]:%016llx  cr[4]:%016llx\n",
+				((QEMUCPUState *)uptr)->cr[3],
+				((QEMUCPUState *)uptr)->cr[4]);
+	}
+
 	if (BITS32() && (xen_core || (note->n_type == NT_PRSTATUS))) {
 		iptr = (int *)uptr;
 		for (i = lf = 0; i < note->n_descsz/sizeof(ulong); i++) {
diff --git a/netdump.h b/netdump.h
index 4a6d661..ba6fde6 100644
--- a/netdump.h
+++ b/netdump.h
@@ -177,3 +177,25 @@ struct proc_kcore_data {
 	Elf32_Phdr *load32;
 };
 
+struct QEMUCPUSegment {
+    uint32_t selector;
+    uint32_t limit;
+    uint32_t flags;
+    uint32_t pad;
+    uint64_t base;
+};
+
+typedef struct QEMUCPUSegment QEMUCPUSegment;
+
+struct QEMUCPUState {
+    uint32_t version;
+    uint32_t size;
+    uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
+    uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
+    uint64_t rip, rflags;
+    QEMUCPUSegment cs, ds, es, fs, gs, ss;
+    QEMUCPUSegment ldt, tr, gdt, idt;
+    uint64_t cr[5];
+};
+
+typedef struct QEMUCPUState QEMUCPUState;
-- 
1.7.1

>From 681af5e8e0447559aa371336c25280828368637a Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@xxxxxxxxxxxxxx>
Date: Sun, 22 Jul 2012 10:22:48 +0800
Subject: [PATCH 1/3] add support to qemu memory dump

---
 defs.h    |    1 +
 main.c    |    2 +
 netdump.c |  104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 103 insertions(+), 4 deletions(-)

diff --git a/defs.h b/defs.h
index caa87c0..f9240e9 100755
--- a/defs.h
+++ b/defs.h
@@ -484,6 +484,7 @@ struct program_context {
 #define ERASEINFO_DATA (0x10ULL)
 #define GDB_CMD_MODE   (0x20ULL)
 #define LIVE_DUMP      (0x40ULL)
+#define QEMU_MEM_DUMP  (0x80ULL)
 #define FLAT_FORMAT() (pc->flags2 & FLAT)
 #define ELF_NOTES_VALID() (pc->flags2 & ELF_NOTES)
 	char *cleanup;
diff --git a/main.c b/main.c
index 7b06cc9..e397646 100755
--- a/main.c
+++ b/main.c
@@ -1315,6 +1315,8 @@ dump_program_context(void)
 		fprintf(fp, "%sREMOTE_DAEMON", others++ ? "|" : "");
 	if (pc->flags2 & LIVE_DUMP)
 		fprintf(fp, "%sLIVE_DUMP", others++ ? "|" : "");
+	if (pc->flags2 & QEMU_MEM_DUMP)
+		fprintf(fp, "%sQEMU_MEM_DUMP", others++ ? "|" : "");
 	fprintf(fp, ")\n");
 
 	fprintf(fp, "         namelist: %s\n", pc->namelist);
diff --git a/netdump.c b/netdump.c
index 9fecbf3..338fb4a 100644
--- a/netdump.c
+++ b/netdump.c
@@ -42,6 +42,7 @@ static int proc_kcore_init_32(FILE *fp);
 static int proc_kcore_init_64(FILE *fp);
 static char *get_regs_from_note(char *, ulong *, ulong *);
 static void kdump_get_osrelease(void);
+static int check_elf_note(char *, int , char *, int);
 
 #define ELFSTORE 1
 #define ELFREAD  0
@@ -205,9 +206,11 @@ is_netdump(char *file, ulong source_query)
                 size = (size_t)load32->p_offset;
 
 		if ((load32->p_offset & (MIN_PAGE_SIZE-1)) &&
-		    (load32->p_align == 0))
+		    (load32->p_align == 0)) {
                 	tmp_flags |= KDUMP_ELF32;
-		else
+			if (check_elf_note(eheader, fd, file, 0))
+				pc->flags2 |= QEMU_MEM_DUMP;
+		} else
                 	tmp_flags |= NETDUMP_ELF32;
 	} else if ((elf64->e_ident[EI_CLASS] == ELFCLASS64) &&
 	    (swap16(elf64->e_type, swap) == ET_CORE) &&
@@ -258,9 +261,11 @@ is_netdump(char *file, ulong source_query)
                         &eheader[sizeof(Elf64_Ehdr)+sizeof(Elf64_Phdr)];
                 size = (size_t)load64->p_offset;
 		if ((load64->p_offset & (MIN_PAGE_SIZE-1)) &&
-		    (load64->p_align == 0))
+		    (load64->p_align == 0)) {
                 	tmp_flags |= KDUMP_ELF64;
-		else
+			if (check_elf_note(eheader, fd, file, 1))
+				pc->flags2 |= QEMU_MEM_DUMP;
+		} else
                 	tmp_flags |= NETDUMP_ELF64;
 	} else {
 		if (CRASHDEBUG(2))
@@ -3475,3 +3480,94 @@ kdump_get_osrelease(void)
 	} else 
 		pc->flags2 &= ~GET_OSRELEASE;
 }
+
+static int
+check_elf_note(char *eheader, int fd, char *file, int machine_type)
+{
+	int qemu_memory_dump;
+	Elf32_Phdr *load32;
+	Elf64_Phdr *load64;
+	ulong offset;
+	ulong filesz;
+	char *pnotes;
+	char buf[BUFSIZE];
+	char *tmp_note;
+	Elf32_Nhdr *tmp_note32;
+	Elf64_Nhdr *tmp_note64;
+	uint32_t namesz, descsz, type;
+	char *name, *desc;
+
+	qemu_memory_dump  = FALSE;
+
+	load32 = (Elf32_Phdr *)&eheader[sizeof(Elf32_Ehdr)];
+	load64 = (Elf64_Phdr *)&eheader[sizeof(Elf64_Ehdr)];
+
+	if (machine_type == 0) {
+		if (!(load32->p_type == PT_NOTE))
+			return qemu_memory_dump;
+
+		offset = load32->p_offset;
+		filesz = load32->p_filesz;
+	} else {
+		if (!(load64->p_type == PT_NOTE))
+			return qemu_memory_dump;
+
+		offset = load64->p_offset;
+		filesz = load64->p_filesz;
+	}
+
+	if ((pnotes = (char *)malloc(filesz)) == NULL) {
+		fprintf(stderr, "cannot malloc elf note buffer\n");
+		clean_exit(1);
+	}
+
+	if (FLAT_FORMAT()) {
+		if (!read_flattened_format(fd, offset, pnotes, filesz)) {
+			free(pnotes);
+			return qemu_memory_dump;
+		}
+	} else {
+		if (lseek(fd, offset, SEEK_SET) != offset) {
+			sprintf(buf, "%s: lseek", file);
+			perror(buf);
+			return qemu_memory_dump;
+		}
+		if (read(fd, pnotes, filesz) != filesz) {
+			sprintf(buf, "%s: read", file);
+			perror(buf);
+			free(pnotes);
+			return qemu_memory_dump;
+		}
+	}
+
+	tmp_note = pnotes;
+
+	while (tmp_note < pnotes + filesz)
+	{
+		if (machine_type == 0) {
+			tmp_note32 = (Elf32_Nhdr *)tmp_note;
+			namesz = tmp_note32->n_namesz;
+			descsz = tmp_note32->n_descsz;
+			type = tmp_note32->n_type;
+
+			name = (char *)tmp_note + ((sizeof(Elf32_Nhdr) + 3) / 4) * 4;
+		} else {
+			tmp_note64 = (Elf64_Nhdr *)tmp_note;
+			namesz = tmp_note64->n_namesz;
+			descsz = tmp_note64->n_descsz;
+			type = tmp_note64->n_type;
+
+			name = (char *)tmp_note + ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
+		}
+		desc = name + ((namesz + 3) / 4) * 4;
+
+		if (STREQ(name, "QEMU")) {
+			qemu_memory_dump = TRUE;
+			break;
+		}
+		
+		tmp_note = desc + (descsz + 3) / 4 * 4;
+	}
+
+	return qemu_memory_dump;
+}
-- 
1.7.1

>From 866fcb3229996b5d710779f93a0df01d57720caf Mon Sep 17 00:00:00 2001
From: qiaonuohan <qiaonuohan@xxxxxxxxxxxxxx>
Date: Sun, 22 Jul 2012 10:23:58 +0800
Subject: [PATCH 2/3] support core dump file when kdump is operating

---
 defs.h    |    3 +
 main.c    |    2 +
 netdump.c |  224 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 netdump.h |    5 ++
 4 files changed, 234 insertions(+), 0 deletions(-)

diff --git a/defs.h b/defs.h
index f9240e9..431a97b 100755
--- a/defs.h
+++ b/defs.h
@@ -270,6 +270,8 @@ struct number_option {
 #define KCORE_LOCAL    (0x100)     
 #define KCORE_ELF32    (0x200)
 #define KCORE_ELF64    (0x400)
+#define QEMU_MEM_DUMP_KDUMP_BACKUP \
+                       (0x800)
 #define KVMDUMP_LOCAL    (0x1)
 #define KVMDUMP_VALID()  (kvm->flags & (KVMDUMP_LOCAL))
 
@@ -4983,6 +4985,7 @@ int proc_kcore_init(FILE *);
 int read_proc_kcore(int, void *, int, ulong, physaddr_t);
 int write_proc_kcore(int, void *, int, ulong, physaddr_t);
 int kcore_memory_dump(FILE *);
+void qemu_mem_dump_kdump_backup_region_init(void);
 
 /*
  *  diskdump.c
diff --git a/main.c b/main.c
index e397646..6bcd823 100755
--- a/main.c
+++ b/main.c
@@ -627,6 +627,8 @@ main_loop(void)
         if (!(pc->flags & GDB_INIT)) {
 		gdb_session_init();
 		show_untrusted_files();
+		if (pc->flags2 & QEMU_MEM_DUMP)
+			qemu_mem_dump_kdump_backup_region_init();
 		if (SADUMP_DUMPFILE())
 			sadump_kdump_backup_region_init();
 		if (XEN_HYPER_MODE()) {
diff --git a/netdump.c b/netdump.c
index 338fb4a..e3cc1ce 100644
--- a/netdump.c
+++ b/netdump.c
@@ -507,6 +507,20 @@ read_netdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
 	off_t offset;
 	struct pt_load_segment *pls;
 	int i;
+ 
+	if (nd->flags & QEMU_MEM_DUMP_KDUMP_BACKUP &&
+	    paddr >= nd->backup_src_start &&
+	    paddr < nd->backup_src_start + nd->backup_src_size) {
+		ulong orig_paddr;
+
+		orig_paddr = paddr;
+		paddr += nd->backup_offset - nd->backup_src_start;
+
+		if (CRASHDEBUG(1))
+			error(INFO,
+			    "qemu_mem_dump: kdump backup region: %#llx => %#llx\n",
+			    orig_paddr, paddr);
+	}
 
 	offset = 0;
 
@@ -3571,3 +3585,213 @@ check_elf_note(char *eheader, int fd, char *file, int machine_type)
 
 	return qemu_memory_dump;
 }
+
+/**
+ * kdump saves the first 640kB physical memory for BIOS to use the
+ * range on boot of 2nd kernel. qemu mem dump translates read request to the
+ * 640kB region as to the back up region. This function seachs kexec
+ * resources for the backup region.
+ */
+void
+qemu_mem_dump_kdump_backup_region_init(void)
+{
+	char buf[BUFSIZE];
+	ulong i, total, kexec_crash_image_p, elfcorehdr_p;
+	uint16_t e_phnum, e_phentsize;
+	ulong backup_offset;
+	ulong backup_src_start, backup_src_size;
+	int kimage_segment_len;
+	size_t bufsize;
+
+	Elf64_Off e_phoff64 = 0;
+	Elf32_Off e_phoff32 = 0;
+
+	if (!readmem(symbol_value("kexec_crash_image"), KVADDR,
+		     &kexec_crash_image_p, sizeof(ulong),
+		     "kexec backup region: kexec_crash_image",
+		     QUIET|RETURN_ON_ERROR))
+		goto error;
+
+	if (!kexec_crash_image_p) {
+		if (CRASHDEBUG(1))
+			error(INFO, "qemu mem dump: kexec_crash_image not loaded\n");
+		return;
+	}
+
+	kimage_segment_len = get_array_length("kimage.segment", NULL,
+					      STRUCT_SIZE("kexec_segment"));
+
+	if (!readmem(kexec_crash_image_p + MEMBER_OFFSET("kimage", "segment"),
+		     KVADDR, buf, MEMBER_SIZE("kimage", "segment"),
+		     "kexec backup region: kexec_crash_image->segment",
+		     QUIET|RETURN_ON_ERROR))
+		goto error;
+
+	elfcorehdr_p = 0;
+	for (i = 0; i < kimage_segment_len; ++i) {
+		char e_ident[EI_NIDENT];
+		ulong mem;
+
+		mem = ULONG(buf + i * STRUCT_SIZE("kexec_segment") +
+			    MEMBER_OFFSET("kexec_segment", "mem"));
+		if (!mem)
+			continue;
+
+		if (!readmem(mem, PHYSADDR, e_ident, SELFMAG,
+			     "elfcorehdr: e_ident",
+			     QUIET|RETURN_ON_ERROR))
+			goto error;
+
+		if (strncmp(ELFMAG, e_ident, SELFMAG) == 0) {
+			elfcorehdr_p = mem;
+			break;
+		}
+	}
+	if (!elfcorehdr_p) {
+		if (CRASHDEBUG(1))
+			error(INFO,
+	"qemu mem dump: elfcorehdr not found in segments of kexec_crash_image\n");
+		goto error;
+	}
+	
+	if (nd->flags & KDUMP_ELF32) {
+		if (!readmem(elfcorehdr_p, PHYSADDR, buf, STRUCT_SIZE("elf32_hdr"),
+			"elfcorehdr", QUIET|RETURN_ON_ERROR))
+			goto error;
+
+		e_phnum = USHORT(buf + MEMBER_OFFSET("elf32_hdr", "e_phnum"));
+		e_phentsize = USHORT(buf + MEMBER_OFFSET("elf32_hdr", "e_phentsize"));
+		e_phoff32 = ULONG(buf + MEMBER_OFFSET("elf32_hdr", "e_phoff"));
+	} else {
+		if (!readmem(elfcorehdr_p, PHYSADDR, buf, STRUCT_SIZE("elf64_hdr"),
+			    "elfcorehdr", QUIET|RETURN_ON_ERROR))
+			goto error;
+
+		e_phnum = USHORT(buf + MEMBER_OFFSET("elf64_hdr", "e_phnum"));
+		e_phentsize = USHORT(buf + MEMBER_OFFSET("elf64_hdr", "e_phentsize"));
+		e_phoff64 = ULONG(buf + MEMBER_OFFSET("elf64_hdr", "e_phoff"));
+	}
+
+	backup_src_start = backup_src_size = backup_offset = 0;
+
+	for (i = 0; i < e_phnum; ++i) {
+		uint32_t p_type;
+		Elf32_Off p_offset32 = 0;
+		Elf64_Off p_offset64 = 0;
+		Elf32_Addr p_paddr32 = 0;
+		Elf64_Addr p_paddr64 = 0;
+		uint32_t p_memsz32 = 0;
+		uint64_t p_memsz64 = 0;
+
+		if (nd->flags & KDUMP_ELF32) {
+			if (!readmem(elfcorehdr_p + e_phoff32 + i * e_phentsize,
+				    PHYSADDR, buf, e_phentsize,
+				    "elfcorehdr: program header",
+				    QUIET|RETURN_ON_ERROR))
+				goto error;
+
+			p_type = UINT(buf+MEMBER_OFFSET("elf32_phdr","p_type"));
+			p_offset32 = ULONG(buf+MEMBER_OFFSET("elf32_phdr","p_offset"));
+			p_paddr32 = ULONG(buf+MEMBER_OFFSET("elf32_phdr","p_paddr"));
+			p_memsz32 = ULONG(buf+MEMBER_OFFSET("elf32_phdr","p_memsz"));
+		} else {
+			if (!readmem(elfcorehdr_p + e_phoff64 + i * e_phentsize,
+				    PHYSADDR, buf, e_phentsize,
+				    "elfcorehdr: program header",
+				    QUIET|RETURN_ON_ERROR))
+				goto error;
+
+			p_type = UINT(buf+MEMBER_OFFSET("elf64_phdr","p_type"));
+			p_offset64 = ULONG(buf+MEMBER_OFFSET("elf64_phdr","p_offset"));
+			p_paddr64 = ULONG(buf+MEMBER_OFFSET("elf64_phdr","p_paddr"));
+			p_memsz64 = ULONG(buf+MEMBER_OFFSET("elf64_phdr","p_memsz"));
+		}
+
+		/*
+		 * kexec marks backup region PT_LOAD by assigning
+		 * backup region address in p_offset, and p_addr in
+		 * p_offsets for other PT_LOAD entries.
+		 */
+		if (nd->flags & KDUMP_ELF32) {
+			if (p_type == PT_LOAD &&
+			    p_paddr32 <= KEXEC_BACKUP_SRC_END &&
+			    p_paddr32 != p_offset32) {
+
+				backup_src_start = p_paddr32;
+				backup_src_size = p_memsz32;
+				backup_offset = p_offset32;
+
+				if (CRASHDEBUG(1))
+					error(INFO,
+				"qemu mem dump: kexec backup region found: "
+				"START: %#08lx SIZE: %#08lx OFFSET: %#08lx\n",
+				backup_src_start, backup_src_size, backup_offset);
+
+				break;
+			}
+		} else {
+			if (p_type == PT_LOAD &&
+			    p_paddr64 <= KEXEC_BACKUP_SRC_END &&
+			    p_paddr64 != p_offset64) {
+
+				backup_src_start = p_paddr64;
+				backup_src_size = p_memsz64;
+				backup_offset = p_offset64;
+
+				if (CRASHDEBUG(1))
+					error(INFO,
+				"qemu mem dump: kexec backup region found: "
+				"START: %#016lx SIZE: %#016lx OFFSET: %#016lx\n",
+				backup_src_start, backup_src_size, backup_offset);
+
+				break;
+			}
+		}
+	}
+
+	if (!backup_offset) {
+		if (CRASHDEBUG(1))
+	error(WARNING, "qemu mem dump: backup region not found in elfcorehdr\n");
+		return;
+	}
+
+	bufsize = BUFSIZE;
+	for (total = 0; total < backup_src_size; total += bufsize) {
+		char backup_buf[BUFSIZE];
+		int j;
+
+		if (backup_src_size - total < BUFSIZE)
+			bufsize = backup_src_size - total;
+
+		if (!readmem(backup_offset + total, PHYSADDR, backup_buf,
+			     bufsize, "backup source", QUIET|RETURN_ON_ERROR))
+			goto error;
+
+		/*
+		 * We're assuming the backup resion is initialized
+		 * with 0 filled if kdump has not run.
+		 */
+		for (j = 0; j < bufsize; ++j) {
+			if (backup_buf[j]) {
+
+				nd->flags |= QEMU_MEM_DUMP_KDUMP_BACKUP;
+				nd->backup_src_start = backup_src_start;
+				nd->backup_src_size = backup_src_size;
+				nd->backup_offset = backup_offset;
+
+				if (CRASHDEBUG(1))
+error(INFO, "qemu mem dump: backup region is used: %lx\n", backup_offset + total + j);
+
+				return;
+			}
+		}
+	}
+
+	if (CRASHDEBUG(1))
+		error(INFO, "qemu mem dump: kexec backup region not used\n");
+
+	return;
+
+error:
+	error(WARNING, "failed to init kexec backup region\n");
+}
diff --git a/netdump.h b/netdump.h
index 2e296ad..4a6d661 100644
--- a/netdump.h
+++ b/netdump.h
@@ -71,6 +71,11 @@ struct vmcore_data {
 	struct xen_kdump_data *xen_kdump_data;
 	void *vmcoreinfo;
 	uint size_vmcoreinfo;
+/* Backup Region, First 640K of System RAM. */
+#define KEXEC_BACKUP_SRC_END	0x0009ffff
+	ulong backup_src_start;
+	ulong backup_src_size;
+	ulong backup_offset;
 };
 
 /*
-- 
1.7.1

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux