At 2012-8-21 23:18, Dave Anderson wrote:
Can you change your patch so that they are the same?
And would you like to work on creating the new common
kdump_backup_region_init() function that can handle both
vmcore_data and sadump_data structures?
Please refer to the attachments. The first two are used to support qemu
memory dump file. And I made the 4th patch to rewrite function
kdump_backup_region_init() based on HATAYAMA's patch(the 3rd patch).
--
--
Regards
Qiao Nuohan
>From 0d9e9498a301a3d14fb6b5b0449c2aaf4d072252 Mon Sep 17 00:00:00 2001
From: qiaonuohan <[email protected]>
Date: Wed, 22 Aug 2012 16:46:20 +0800
Subject: [PATCH 4/4] support core dump file with kdump backup region
---
defs.h | 6 +-
main.c | 3 +-
netdump.c | 270 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
netdump.h | 5 +
sadump.c | 163 +------------------------------------
5 files changed, 284 insertions(+), 163 deletions(-)
diff --git a/defs.h b/defs.h
index 96c9997..444888e 100755
--- a/defs.h
+++ b/defs.h
@@ -273,6 +273,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))
@@ -5006,6 +5008,8 @@ 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 dump_register_for_qemu_mem_dump(void);
+void *get_vmcore_data(void);
+void kdump_backup_region_init(void);
/*
* diskdump.c
@@ -5115,7 +5119,7 @@ void sadump_show_diskset(void);
int sadump_is_zero_excluded(void);
void sadump_set_zero_excluded(void);
void sadump_unset_zero_excluded(void);
-void sadump_kdump_backup_region_init(void);
+void *get_sadump_data(void);
/*
* qemu.c
diff --git a/main.c b/main.c
index 9dced6e..7650b8c 100755
--- a/main.c
+++ b/main.c
@@ -640,8 +640,7 @@ main_loop(void)
if (!(pc->flags & GDB_INIT)) {
gdb_session_init();
show_untrusted_files();
- if (SADUMP_DUMPFILE())
- sadump_kdump_backup_region_init();
+ kdump_backup_region_init();
if (XEN_HYPER_MODE()) {
#ifdef XEN_HYPERVISOR_ARCH
machdep_init(POST_GDB);
diff --git a/netdump.c b/netdump.c
index bdc2757..b4f0311 100644
--- a/netdump.c
+++ b/netdump.c
@@ -20,6 +20,7 @@
#include "defs.h"
#include "netdump.h"
+#include "sadump.h"
static struct vmcore_data vmcore_data = { 0 };
static struct vmcore_data *nd = &vmcore_data;
@@ -932,6 +933,8 @@ netdump_memory_dump(FILE *fp)
netdump_print("%sKDUMP_ELF64", others++ ? "|" : "");
if (nd->flags & PARTIAL_DUMP)
netdump_print("%sPARTIAL_DUMP", others++ ? "|" : "");
+ if (nd->flags & QEMU_MEM_DUMP_KDUMP_BACKUP)
+ netdump_print("%sQEMU_MEM_DUMP_KDUMP_BACKUP", others++ ? "|" : "");
netdump_print(") %s\n", FLAT_FORMAT() ? "[FLAT]" : "");
if ((pc->flags & RUNTIME) && symbol_exists("dump_level")) {
int dump_level;
@@ -1072,6 +1075,10 @@ netdump_memory_dump(FILE *fp)
}
}
netdump_print("\n");
+ netdump_print(" backup_src_start: %llx\n", nd->backup_src_start);
+ netdump_print(" backup_src_size: %lx\n", nd->backup_src_size);
+ netdump_print(" backup_offset: %llx\n", nd->backup_offset);
+ netdump_print("\n");
switch (DUMPFILE_FORMAT(nd->flags))
{
@@ -2746,6 +2753,18 @@ read_kdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
{
physaddr_t paddr_in = paddr;
+ if (nd->flags & QEMU_MEM_DUMP_KDUMP_BACKUP &&
+ paddr >= nd->backup_src_start &&
+ paddr < nd->backup_src_start + nd->backup_src_size) {
+
+ paddr += nd->backup_offset - nd->backup_src_start;
+
+ if (CRASHDEBUG(1))
+ error(INFO,
+ "qemu_mem_dump: kdump backup region: %#llx => %#llx\n",
+ paddr_in, paddr);
+ }
+
if (XEN_CORE_DUMPFILE() && !XEN_HYPER_MODE()) {
if (!(nd->xen_kdump_data->flags & KDUMP_P2M_INIT)) {
if (!machdep->xen_kdump_p2m_create)
@@ -3605,3 +3624,254 @@ dump_register_for_qemu_mem_dump(void)
nd->ofp = fpsave;
}
+
+void *
+get_vmcore_data(void)
+{
+ return nd;
+}
+
+/**
+ * kdump saves the first 640kB physical memory for BIOS to use the
+ * range on boot of 2nd kernel. Read request to the 640k should be
+ * translated to the back up region. This function searches kexec
+ * resources for the backup region.
+ */
+void
+kdump_backup_region_init(void)
+{
+ char buf[BUFSIZE];
+ ulong i, total, kexec_crash_image_p, elfcorehdr_p;
+ Elf32_Off e_phoff32;
+ Elf64_Off e_phoff64;
+ uint16_t e_phnum, e_phentsize;
+ ulonglong backup_offset;
+ ulonglong backup_src_start;
+ ulong backup_src_size;
+ int kimage_segment_len;
+ size_t bufsize;
+ void *vd;
+ int archflag; /* indicate the arch of core file: 1 -> 32bit */
+ char typename[BUFSIZE];
+
+ e_phoff32 = e_phoff64 = 0;
+ archflag = 0;
+
+ if (SADUMP_DUMPFILE()) {
+ vd = get_sadump_data();
+ archflag = 0;
+ sprintf(typename, "sadump");
+ } else if (pc->flags2 & QEMU_MEM_DUMP) {
+ vd = get_vmcore_data();
+ if (((struct vmcore_data *)vd)->flags & KDUMP_ELF32)
+ archflag = 1;
+ else
+ archflag = 0;
+ sprintf(typename, "qemu mem dump");
+ } else
+ return;
+
+ 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, "%s: kexec_crash_image not loaded\n", typename);
+ 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,
+ "%s: elfcorehdr not found in segments of kexec_crash_image\n", typename);
+ goto error;
+ }
+
+ if (archflag) {
+ 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;
+ Elf64_Off p_offset64;
+ Elf32_Addr p_paddr32;
+ Elf64_Addr p_paddr64;
+ uint32_t p_memsz32;
+ uint64_t p_memsz64;
+
+ if (archflag) {
+ 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 (archflag) {
+ 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,
+ "%s: kexec backup region found: "
+ "START: %#016llx SIZE: %#016lx OFFSET: %#016llx\n",
+ typename, 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,
+ "%s: kexec backup region found: "
+ "START: %#016llx SIZE: %#016lx OFFSET: %#016llx\n",
+ typename, backup_src_start, backup_src_size, backup_offset);
+
+ break;
+ }
+ }
+ }
+
+ if (!backup_offset) {
+ if (CRASHDEBUG(1))
+ error(WARNING, "%s: backup region not found in elfcorehdr\n", typename);
+ 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 region is initialized
+ * with 0 filled if kdump has not run.
+ */
+ for (j = 0; j < bufsize; ++j) {
+ if (backup_buf[j]) {
+
+ if (SADUMP_DUMPFILE()) {
+ ((struct sadump_data *)vd)->flags |=
+ SADUMP_KDUMP_BACKUP;
+ ((struct sadump_data *)vd)->backup_src_start =
+ backup_src_start;
+ ((struct sadump_data *)vd)->backup_src_size =
+ backup_src_size;
+ ((struct sadump_data *)vd)->backup_offset =
+ backup_offset;
+ } else if (pc->flags2 & QEMU_MEM_DUMP) {
+ ((struct vmcore_data *)vd)->flags |=
+ QEMU_MEM_DUMP_KDUMP_BACKUP;
+ ((struct vmcore_data *)vd)->backup_src_start =
+ backup_src_start;
+ ((struct vmcore_data *)vd)->backup_src_size =
+ backup_src_size;
+ ((struct vmcore_data *)vd)->backup_offset =
+ backup_offset;
+ }
+
+ if (CRASHDEBUG(1))
+error(INFO, "%s: backup region is used: %llx\n", typename, backup_offset + total + j);
+
+ return;
+ }
+ }
+ }
+
+ if (CRASHDEBUG(1))
+ error(INFO, "%s: kexec backup region not used\n", typename);
+
+ return;
+
+error:
+ error(WARNING, "failed to init kexec backup region\n");
+}
diff --git a/netdump.h b/netdump.h
index 0c49871..98735e3 100644
--- a/netdump.h
+++ b/netdump.h
@@ -73,6 +73,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
+ ulonglong backup_src_start;
+ ulong backup_src_size;
+ ulonglong backup_offset;
};
/*
diff --git a/sadump.c b/sadump.c
index f15d6de..a1fc685 100644
--- a/sadump.c
+++ b/sadump.c
@@ -1608,165 +1608,8 @@ void sadump_unset_zero_excluded(void)
sd->flags &= ~SADUMP_ZERO_EXCLUDED;
}
-/**
- * kdump saves the first 640kB physical memory for BIOS to use the
- * range on boot of 2nd kernel. sadump translates read request to the
- * 640kB region as to the back up region. This function seachs kexec
- * resources for the backup region.
- */
-void sadump_kdump_backup_region_init(void)
+void *
+get_sadump_data(void)
{
- char buf[BUFSIZE];
- ulong i, total, kexec_crash_image_p, elfcorehdr_p;
- Elf64_Off e_phoff;
- uint16_t e_phnum, e_phentsize;
- uint64_t backup_offset;
- ulonglong backup_src_start;
- ulong backup_src_size;
- int kimage_segment_len;
- size_t bufsize;
-
- 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, "sadump: 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,
- "sadump: elfcorehdr not found in segments of kexec_crash_image\n");
- goto error;
- }
- 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_phoff = 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;
- Elf64_Off p_offset;
- Elf64_Addr p_paddr;
- uint64_t p_memsz;
-
- if (!readmem(elfcorehdr_p + e_phoff + i * e_phentsize,
- PHYSADDR, buf, e_phentsize,
- "elfcorehdr: program heaer",
- QUIET|RETURN_ON_ERROR))
- goto error;
-
- p_type = UINT(buf+MEMBER_OFFSET("elf64_phdr","p_type"));
- p_offset=ULONGLONG(buf+MEMBER_OFFSET("elf64_phdr","p_offset"));
- p_paddr = ULONGLONG(buf+MEMBER_OFFSET("elf64_phdr","p_paddr"));
- p_memsz = ULONGLONG(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 (p_type == PT_LOAD &&
- p_paddr <= KEXEC_BACKUP_SRC_END &&
- p_paddr != p_offset) {
-
- backup_src_start = p_paddr;
- backup_src_size = p_memsz;
- backup_offset = p_offset;
-
- if (CRASHDEBUG(1))
- error(INFO,
- "sadump: kexec backup region found: "
- "START: %#016llx SIZE: %#016lx OFFSET: %#016llx\n",
- backup_src_start, backup_src_size, backup_offset);
-
- break;
- }
- }
-
- if (!backup_offset) {
- if (CRASHDEBUG(1))
- error(WARNING, "sadump: 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]) {
-
- sd->flags |= SADUMP_KDUMP_BACKUP;
- sd->backup_src_start = backup_src_start;
- sd->backup_src_size = backup_src_size;
- sd->backup_offset = backup_offset;
-
- if (CRASHDEBUG(1))
-error(INFO, "sadump: backup region is used: %lx\n", backup_offset + total + j);
-
- return;
- }
- }
- }
-
- if (CRASHDEBUG(1))
- error(INFO, "sadump: kexec backup region not used\n");
-
- return;
-
-error:
- error(WARNING, "failed to init kexec backup region\n");
-
+ return sd;
}
--
1.7.1
>From c1a5e370e12947ef205d7adc12cb4b6f923326fb Mon Sep 17 00:00:00 2001
From: qiaonuohan <[email protected]>
Date: Wed, 22 Aug 2012 14:40:18 +0800
Subject: [PATCH 1/4] add support to qemu memory dump
---
defs.h | 1 +
main.c | 2 ++
netdump.c | 16 ++++++++++++----
3 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/defs.h b/defs.h
index 4a8e2e3..d37e453 100755
--- a/defs.h
+++ b/defs.h
@@ -492,6 +492,7 @@ struct program_context {
#define FLAT_FORMAT() (pc->flags2 & FLAT)
#define ELF_NOTES_VALID() (pc->flags2 & ELF_NOTES)
#define RADIX_OVERRIDE (0x80ULL)
+#define QEMU_MEM_DUMP (0x100ULL)
char *cleanup;
char *namelist_orig;
char *namelist_debug_orig;
diff --git a/main.c b/main.c
index 2dbe902..9dced6e 100755
--- a/main.c
+++ b/main.c
@@ -1330,6 +1330,8 @@ dump_program_context(void)
fprintf(fp, "%sLIVE_DUMP", others++ ? "|" : "");
if (pc->flags2 & RADIX_OVERRIDE)
fprintf(fp, "%sRADIX_OVERRIDE", 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..55073dd 100644
--- a/netdump.c
+++ b/netdump.c
@@ -1670,13 +1670,13 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
char buf[BUFSIZE];
char *ptr;
ulong *uptr;
- int xen_core, vmcoreinfo, eraseinfo;
+ int xen_core, vmcoreinfo, eraseinfo, qemuinfo;
uint64_t remaining, notesize;
note = (Elf32_Nhdr *)((char *)nd->elf32 + offset);
BZERO(buf, BUFSIZE);
- xen_core = vmcoreinfo = eraseinfo = FALSE;
+ xen_core = vmcoreinfo = eraseinfo = qemuinfo = FALSE;
ptr = (char *)note + sizeof(Elf32_Nhdr);
if (ptr > (nd->elf_header + nd->header_size)) {
@@ -1767,6 +1767,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");
+ qemuinfo = STRNEQ(buf, "QEMU");
if (xen_core) {
netdump_print("(unknown Xen n_type)\n");
if (store)
@@ -1785,6 +1786,9 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
pc->flags2 |= ERASEINFO_DATA;
} else
netdump_print("(?)\n");
+
+ if (qemuinfo)
+ pc->flags2 |= QEMU_MEM_DUMP;
break;
case NT_XEN_KDUMP_CR3:
@@ -1900,14 +1904,14 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
ulonglong *uptr;
int *iptr;
ulong *up;
- int xen_core, vmcoreinfo, eraseinfo;
+ int xen_core, vmcoreinfo, eraseinfo, qemuinfo;
uint64_t remaining, notesize;
note = (Elf64_Nhdr *)((char *)nd->elf64 + offset);
BZERO(buf, BUFSIZE);
ptr = (char *)note + sizeof(Elf64_Nhdr);
- xen_core = vmcoreinfo = eraseinfo = FALSE;
+ xen_core = vmcoreinfo = eraseinfo = qemuinfo = FALSE;
if (ptr > (nd->elf_header + nd->header_size)) {
error(WARNING,
@@ -2028,6 +2032,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");
+ qemuinfo = STRNEQ(buf, "QEMU");
if (xen_core) {
netdump_print("(unknown Xen n_type)\n");
if (store)
@@ -2050,6 +2055,9 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
pc->flags2 |= ERASEINFO_DATA;
} else
netdump_print("(?)\n");
+
+ if (qemuinfo)
+ pc->flags2 |= QEMU_MEM_DUMP;
break;
case NT_XEN_KDUMP_CR3:
--
1.7.1
>From 518dfa90c198fa75e715d9715b59f4a42902743c Mon Sep 17 00:00:00 2001
From: qiaonuohan <[email protected]>
Date: Wed, 22 Aug 2012 14:40:51 +0800
Subject: [PATCH 2/4] display registers stored in qemu note section
---
defs.h | 2 +
help.c | 15 ++++++-
netdump.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
netdump.h | 24 +++++++++++
4 files changed, 167 insertions(+), 6 deletions(-)
diff --git a/defs.h b/defs.h
index d37e453..96c9997 100755
--- a/defs.h
+++ b/defs.h
@@ -4211,6 +4211,7 @@ int cleanup_memory_driver(void);
#define END_OF_HELP_DATA "END_OF_HELP_DATA"
void help_init(void);
void cmd_usage(char *, int);
+void dump_register(void);
void display_version(void);
void display_help_screen(char *);
#ifdef ARM
@@ -5004,6 +5005,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 dump_register_for_qemu_mem_dump(void);
/*
* diskdump.c
diff --git a/help.c b/help.c
index 6ab9eea..b292f24 100755
--- a/help.c
+++ b/help.c
@@ -466,7 +466,7 @@ cmd_help(void)
oflag = 0;
while ((c = getopt(argcnt, args,
- "efNDdmM:ngcaBbHhkKsvVoptTzLxO")) != EOF) {
+ "efNDdmM:ngcaBbHhkKsvVoptTzLxOq")) != EOF) {
switch(c)
{
case 'e':
@@ -601,6 +601,10 @@ cmd_help(void)
dumpfile_memory(DUMPFILE_ENVIRONMENT);
return;
+ case 'q':
+ dump_register();
+ return;
+
default:
argerrs++;
break;
@@ -627,6 +631,15 @@ cmd_help(void)
} while (args[optind]);
}
+void
+dump_register(void)
+{
+ if (pc->flags2 & QEMU_MEM_DUMP)
+ dump_register_for_qemu_mem_dump();
+ else
+ option_not_supported('q');
+}
+
/*
* Format and display the help menu.
*/
diff --git a/netdump.c b/netdump.c
index 55073dd..bdc2757 100644
--- a/netdump.c
+++ b/netdump.c
@@ -1042,10 +1042,11 @@ netdump_memory_dump(FILE *fp)
nd->xen_kdump_data->p2m_mfn_frame_list[i]);
if (i) netdump_print("\n");
}
- netdump_print(" num_prstatus_notes: %d\n", nd->num_prstatus_notes);
- netdump_print(" vmcoreinfo: %lx\n", (ulong)nd->vmcoreinfo);
- netdump_print(" size_vmcoreinfo: %d\n", nd->size_vmcoreinfo);
- netdump_print(" nt_prstatus_percpu: ");
+ netdump_print(" num_prstatus_notes: %d\n", nd->num_prstatus_notes);
+ netdump_print(" num_qemu_notes: %d\n", nd->num_qemu_notes);
+ netdump_print(" vmcoreinfo: %lx\n", (ulong)nd->vmcoreinfo);
+ netdump_print(" size_vmcoreinfo: %d\n", nd->size_vmcoreinfo);
+ netdump_print(" nt_prstatus_percpu: ");
wrap = sizeof(void *) == SIZEOF_32BIT ? 8 : 4;
flen = sizeof(void *) == SIZEOF_32BIT ? 8 : 16;
if (nd->num_prstatus_notes == 1)
@@ -1058,7 +1059,19 @@ netdump_memory_dump(FILE *fp)
nd->nt_prstatus_percpu[i]);
}
}
- netdump_print("\n\n");
+ netdump_print("\n");
+ netdump_print(" nt_qemu_percpu: ");
+ if (nd->num_qemu_notes == 1)
+ netdump_print("%.*lx\n", flen, nd->nt_qemu_percpu[0]);
+ else {
+ for (i = 0; i < nd->num_qemu_notes; i++) {
+ if ((i % wrap) == 0)
+ netdump_print("\n ");
+ netdump_print("%.*lx ", flen,
+ nd->nt_qemu_percpu[i]);
+ }
+ }
+ netdump_print("\n");
switch (DUMPFILE_FORMAT(nd->flags))
{
@@ -1861,6 +1874,16 @@ dump_Elf32_Nhdr(Elf32_Off offset, int store)
if (xen_core)
uptr = (ulong *)roundup((ulong)uptr, 4);
+ if (store && qemuinfo) {
+ for(i=0; i<NR_CPUS; i++) {
+ if (!nd->nt_qemu_percpu[i]) {
+ nd->nt_qemu_percpu[i] = (void *)uptr;
+ nd->num_qemu_notes++;
+ break;
+ }
+ }
+ }
+
if (vmcoreinfo || eraseinfo) {
netdump_print(" ");
ptr += note->n_namesz + 1;
@@ -2138,6 +2161,16 @@ dump_Elf64_Nhdr(Elf64_Off offset, int store)
uptr = (ulonglong *)roundup((ulong)uptr, 4);
}
+ if (store && qemuinfo) {
+ for(i=0; i<NR_CPUS; i++) {
+ if (!nd->nt_qemu_percpu[i]) {
+ nd->nt_qemu_percpu[i] = (void *)uptr;
+ nd->num_qemu_notes++;
+ break;
+ }
+ }
+ }
+
if (BITS32() && (xen_core || (note->n_type == NT_PRSTATUS))) {
iptr = (int *)uptr;
for (i = lf = 0; i < note->n_descsz/sizeof(ulong); i++) {
@@ -3483,3 +3516,92 @@ kdump_get_osrelease(void)
} else
pc->flags2 &= ~GET_OSRELEASE;
}
+
+void
+dump_register_for_qemu_mem_dump(void)
+{
+ int i;
+ QEMUCPUState *ptr;
+ FILE *fpsave;
+
+ fpsave = nd->ofp;
+ nd->ofp = fp;
+
+ for (i=0; i<nd->num_qemu_notes; i++) {
+ ptr = (QEMUCPUState *)nd->nt_qemu_percpu[i];
+
+ if (i)
+ netdump_print("\n");
+ netdump_print("CPU %d:\n", i);
+
+ netdump_print(" version:%08lx size:%08lx\n",
+ ptr->version, ptr->size);
+ netdump_print(" rax:%016llx rbx:%016llx rcx:%016llx\n",
+ ptr->rax, ptr->rbx, ptr->rcx);
+ netdump_print(" rdx:%016llx rsi:%016llx rdi:%016llx\n",
+ ptr->rdx, ptr->rsi, ptr->rdi);
+ netdump_print(" rsp:%016llx rbp:%016llx ",
+ ptr->rsp, ptr->rbp);
+
+ if (DUMPFILE_FORMAT(nd->flags) == KDUMP_ELF64) {
+ netdump_print("r8:%016llx\n",
+ ptr->r8);
+ netdump_print(" r9:%016llx r10:%016llx r11:%016llx\n",
+ ptr->r9, ptr->r10, ptr->r11);
+ netdump_print(" r12:%016llx r13:%016llx r14:%016llx\n",
+ ptr->r12, ptr->r13, ptr->r14);
+ netdump_print(" r15:%016llx",
+ ptr->r15);
+ } else
+ netdump_print("\n");
+
+ netdump_print(" rip:%016llx rflags:%016llx\n",
+ ptr->rip, ptr->rflags);
+ netdump_print(" cs:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->cs.selector, ptr->cs.limit, ptr->cs.flags,
+ ptr->cs.pad, ptr->cs.base);
+ netdump_print(" ds:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->ds.selector, ptr->ds.limit, ptr->ds.flags,
+ ptr->ds.pad, ptr->ds.base);
+ netdump_print(" es:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->es.selector, ptr->es.limit, ptr->es.flags,
+ ptr->es.pad, ptr->es.base);
+ netdump_print(" fs:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->fs.selector, ptr->fs.limit, ptr->fs.flags,
+ ptr->fs.pad, ptr->fs.base);
+ netdump_print(" gs:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->gs.selector, ptr->gs.limit, ptr->gs.flags,
+ ptr->gs.pad, ptr->gs.base);
+ netdump_print(" ss:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->ss.selector, ptr->ss.limit, ptr->ss.flags,
+ ptr->ss.pad, ptr->ss.base);
+ netdump_print(" ldt:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->ldt.selector, ptr->ldt.limit, ptr->ldt.flags,
+ ptr->ldt.pad, ptr->ldt.base);
+ netdump_print(" tr:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->tr.selector, ptr->tr.limit, ptr->tr.flags,
+ ptr->tr.pad, ptr->tr.base);
+ netdump_print(" gdt:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->gdt.selector, ptr->gdt.limit, ptr->gdt.flags,
+ ptr->gdt.pad, ptr->gdt.base);
+ netdump_print(" idt:\n selector:%08lx limit:%08lx flags:%08lx\n\
+ pad:%08lx base:%016llx\n",
+ ptr->idt.selector, ptr->idt.limit, ptr->idt.flags,
+ ptr->idt.pad, ptr->idt.base);
+ netdump_print(" cr[0]:%016llx cr[1]:%016llx cr[2]:%016llx\n",
+ ptr->cr[0], ptr->cr[1], ptr->cr[2]);
+ netdump_print(" cr[3]:%016llx cr[4]:%016llx\n",
+ ptr->cr[3], ptr->cr[4]);
+ }
+
+ nd->ofp = fpsave;
+}
diff --git a/netdump.h b/netdump.h
index 2e296ad..0c49871 100644
--- a/netdump.h
+++ b/netdump.h
@@ -67,7 +67,9 @@ struct vmcore_data {
uint page_size;
ulong switch_stack;
uint num_prstatus_notes;
+ uint num_qemu_notes;
void *nt_prstatus_percpu[NR_CPUS];
+ void *nt_qemu_percpu[NR_CPUS];
struct xen_kdump_data *xen_kdump_data;
void *vmcoreinfo;
uint size_vmcoreinfo;
@@ -172,3 +174,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 ee90009d2a2c3b2e64ce29d3d1c8a2489adc1f12 Mon Sep 17 00:00:00 2001
From: qiaonuohan <[email protected]>
Date: Wed, 22 Aug 2012 14:41:18 +0800
Subject: [PATCH 3/4] sadump: Fix invalid truncation of physical address to 32-bit values
---
sadump.c | 7 ++++---
sadump.h | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/sadump.c b/sadump.c
index 795b4f8..f15d6de 100644
--- a/sadump.c
+++ b/sadump.c
@@ -1057,7 +1057,7 @@ int sadump_memory_dump(FILE *fp)
fprintf(fp, " block_table: %lx\n", (ulong)sd->block_table);
fprintf(fp, " sd_list_len: %d\n", sd->sd_list_len);
fprintf(fp, " sd_list: %lx\n", (ulong)sd->sd_list);
- fprintf(fp, " backup_src_start: %lx\n", sd->backup_src_start);
+ fprintf(fp, " backup_src_start: %llx\n", sd->backup_src_start);
fprintf(fp, " backup_src_size: %lx\n", sd->backup_src_size);
fprintf(fp, " backup_offset: %llx\n", (ulonglong)sd->backup_src_size);
@@ -1621,7 +1621,8 @@ void sadump_kdump_backup_region_init(void)
Elf64_Off e_phoff;
uint16_t e_phnum, e_phentsize;
uint64_t backup_offset;
- ulong backup_src_start, backup_src_size;
+ ulonglong backup_src_start;
+ ulong backup_src_size;
int kimage_segment_len;
size_t bufsize;
@@ -1715,7 +1716,7 @@ void sadump_kdump_backup_region_init(void)
if (CRASHDEBUG(1))
error(INFO,
"sadump: kexec backup region found: "
- "START: %#016lx SIZE: %#016lx OFFSET: %#016llx\n",
+ "START: %#016llx SIZE: %#016lx OFFSET: %#016llx\n",
backup_src_start, backup_src_size, backup_offset);
break;
diff --git a/sadump.h b/sadump.h
index 64c2630..29dce06 100644
--- a/sadump.h
+++ b/sadump.h
@@ -204,7 +204,7 @@ struct sadump_data {
/* Backup Region, First 640K of System RAM. */
#define KEXEC_BACKUP_SRC_END 0x0009ffff
- ulong backup_src_start;
+ ulonglong backup_src_start;
ulong backup_src_size;
ulonglong backup_offset;
};
--
1.7.1
--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility