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 <qiaonuohan@xxxxxxxxxxxxxx> 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 <qiaonuohan@xxxxxxxxxxxxxx> 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 <qiaonuohan@xxxxxxxxxxxxxx> 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 <qiaonuohan@xxxxxxxxxxxxxx> 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 Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility