Add new devdump command to analyze and extract hardware specific device dumps in ELF vmcore SYNOPSIS devdump [-l][-i index][-r file] EXAMPLES Display the available device dumps crash> devdump -l 0) name: "cxgb4_0000:02:00.4", file_offset: 0x278 , size: 33558464 1) name: "cxgb4_0000:03:00.4", file_offset: 0x2001278 , size: 33558464 Extract device dump at specified index crash> devdump -i 0 -r device_dump_0.bin 0) name: "cxgb4_0000:02:00.4", file_offset: 0x278 , size: 33558464 33558464 bytes copied from 0x278 to device_dump_0.bin Signed-off-by: Surendra Mobiya <surendra@xxxxxxxxxxx> Signed-off-by: Rahul Lakkireddy <rahul.lakkireddy@xxxxxxxxxxx> --- Makefile | 4 +-- defs.h | 11 ++++++ devdump.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ global_data.c | 1 + help.c | 23 ++++++++++++ memory.c | 7 ++++ netdump.c | 40 +++++++++++++++++++++ 7 files changed, 194 insertions(+), 2 deletions(-) create mode 100644 devdump.c diff --git a/Makefile b/Makefile index f78da15..db72b40 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,7 @@ CFILES=main.c tools.c global_data.c memory.c filesys.c help.c task.c \ xen_hyper.c xen_hyper_command.c xen_hyper_global_data.c \ xen_hyper_dump_tables.c kvmdump.c qemu.c qemu-load.c sadump.c ipcs.c \ ramdump.c vmware_vmss.c \ - xen_dom0.c kaslr_helper.c + xen_dom0.c kaslr_helper.c devdump.c SOURCE_FILES=${CFILES} ${GENERIC_HFILES} ${MCORE_HFILES} \ ${REDHAT_CFILES} ${REDHAT_HFILES} ${UNWIND_HFILES} \ @@ -90,7 +90,7 @@ OBJECT_FILES=main.o tools.o global_data.o memory.o filesys.o help.o task.o \ xen_hyper.o xen_hyper_command.o xen_hyper_global_data.o \ xen_hyper_dump_tables.o kvmdump.o qemu.o qemu-load.o sadump.o ipcs.o \ ramdump.o vmware_vmss.o \ - xen_dom0.o kaslr_helper.o + xen_dom0.o kaslr_helper.o devdump.o MEMORY_DRIVER_FILES=memory_driver/Makefile memory_driver/crash.c memory_driver/README diff --git a/defs.h b/defs.h index 0925a46..41ce61f 100644 --- a/defs.h +++ b/defs.h @@ -4870,6 +4870,7 @@ void cmd_s390dbf(void); #endif void cmd_map(void); /* kvmdump.c */ void cmd_ipcs(void); /* ipcs.c */ +void cmd_devdump(void); /* devdump.c */ /* * main.c @@ -5277,6 +5278,7 @@ char *format_stack_entry(struct bt_info *bt, char *, ulong, ulong); int in_user_stack(ulong, ulong); int dump_inode_page(ulong); ulong valid_section_nr(ulong); +void display_memory_from_file_offset(ulonglong addr, long count, void *opt); /* @@ -5444,6 +5446,7 @@ extern char *help_vtop[]; extern char *help_waitq[]; extern char *help_whatis[]; extern char *help_wr[]; +extern char *help_devdump[]; #if defined(S390) || defined(S390X) extern char *help_s390dbf[]; #endif @@ -6400,6 +6403,8 @@ void *netdump_get_prstatus_percpu(int); int kdump_kaslr_check(void); void display_vmcoredd_note(void *ptr, FILE *ofp); QEMUCPUState *kdump_get_qemucpustate(int); +void kdump_device_dump_info(FILE *logfp); +void kdump_device_dump(int index, char *outfile, FILE *ofp); #define PRSTATUS_NOTE (1) #define QEMU_NOTE (2) @@ -6447,6 +6452,12 @@ int diskdump_kaslr_check(void); QEMUCPUState *diskdump_get_qemucpustate(int); /* + * devdump.c + */ +void devdump_extract(void *note, ulonglong offset, char *dump_file, + FILE *ofp); + +/* * makedumpfile.c */ void check_flattened_format(char *file); diff --git a/devdump.c b/devdump.c new file mode 100644 index 0000000..2b9cbe8 --- /dev/null +++ b/devdump.c @@ -0,0 +1,110 @@ +/* + * devdump.c - device dump analysis suite + * + * Copyright (c) 2019 Chelsio Communications. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Author: Surendra Mobiya <surendra@xxxxxxxxxxx> + */ + +#include <string.h> +#include <stdlib.h> +#include <elf.h> +#include "defs.h" +#include "vmcore.h" + +void cmd_devdump(void) +{ + int opt, index = -1; + char *outputfile; + int list = 0; + + outputfile = NULL; + + if (argcnt == 1) { + error(INFO, "No arg provided"); + return; + } + + while ((opt = getopt(argcnt, args, "r:i:l")) != EOF) { + switch (opt) { + case 'r': + outputfile = optarg; + break; + case 'i': + index = atoi(optarg); + break; + case 'l': + list = 1; + break; + default: + argerrs++; + break; + } + } + + if (argerrs) + cmd_usage(pc->curcmd, SYNOPSIS); + + if (list) { + if (KDUMP_DUMPFILE()) + kdump_device_dump_info(fp); + else + error(WARNING, "KDUMP flag not found"); + } else { + if (index == -1) { + error(INFO, "Index not provided"); + return; + } + + if (!outputfile) { + error(INFO, "Output file not provided"); + return; + } + + if (KDUMP_DUMPFILE()) + kdump_device_dump(index, outputfile, fp); + else + error(WARNING, "KDUMP flag not found"); + } +} + +void +devdump_extract(void *_note, ulonglong offset, char *dump_file, FILE *ofp) +{ + struct vmcoredd_header *vh = (struct vmcoredd_header *)_note; + ulong dump_size; + FILE *tmpfp; + + if (vh->n_type != NT_VMCOREDD) { + error(WARNING, "Unsupported note type 0x%x", vh->n_type); + return; + } + + dump_size = vh->n_descsz - VMCOREDD_MAX_NAME_BYTES; + fprintf(ofp, " name: \"%s\", ", vh->dump_name); + fprintf(ofp, " file_offset: 0x%-10llx,", + offset + sizeof(struct vmcoredd_header)); + fprintf(ofp, " size: %lu\n", dump_size); + if (dump_file) { + tmpfp = fopen(dump_file, "w"); + if (!tmpfp) { + error(FATAL, "cannot open output file: %s\n", + dump_file); + return; + } + set_tmpfile2(tmpfp); + display_memory_from_file_offset(offset + + sizeof(struct vmcoredd_header), + dump_size, dump_file); + } +} diff --git a/global_data.c b/global_data.c index cbacc42..6c42209 100644 --- a/global_data.c +++ b/global_data.c @@ -124,6 +124,7 @@ struct command_table_entry linux_command_table[] = { #if defined(S390) || defined(S390X) {"s390dbf", cmd_s390dbf, help_s390dbf, 0}, #endif + {"devdump", cmd_devdump, help_devdump, 0}, {(char *)NULL} }; diff --git a/help.c b/help.c index 47058ed..fa5818c 100644 --- a/help.c +++ b/help.c @@ -7753,6 +7753,29 @@ char *help_files[] = { NULL }; +char *help_devdump[] = { +"devdump", +"list/extract device dump", +"[-l][-i index][-r file]", +" This command is used to analyze the hardware device dumps collected\n" +" in crash kernel.\n", +" -l list all device dumps present in vmcore", +" -i index Index of the device dump. Use -l command to list the device dump indices", +" -r file output file name ", +"\nEXAMPLES", +" Display the available device dumps", +" crash> devdump -l", +" 0) name: \"cxgb4_0000:02:00.4\", file_offset: 0x278 , size: 33558464", +" 1) name: \"cxgb4_0000:03:00.4\", file_offset: 0x2001278 , size: 33558464", +"", +" Extract device dump at specified index", +" crash> devdump -i 0 -r device_dump_0.bin", +" 0) name: \"cxgb4_0000:02:00.4\", file_offset: 0x278 , size: 33558464", +" 33558464 bytes copied from 0x278 to device_dump_0.bin", +" ", +NULL +}; + char *help_fuser[] = { "fuser", "file users", diff --git a/memory.c b/memory.c index ab561b3..34b7136 100644 --- a/memory.c +++ b/memory.c @@ -1793,6 +1793,13 @@ display_memory(ulonglong addr, long count, ulong flag, int memtype, void *opt) fprintf(fp,"\n"); } +void +display_memory_from_file_offset(ulonglong addr, long count, void *opt) +{ + display_memory(addr, count, DISPLAY_RAW | ASCII_ENDLINE | HEXADECIMAL, + FILEADDR, opt); +} + /* * cmd_wr() is the sister routine of cmd_rd(), used to modify the contents * of memory. Like the "rd" command, the starting address may be entered diff --git a/netdump.c b/netdump.c index c4e9b3e..12e4dfc 100644 --- a/netdump.c +++ b/netdump.c @@ -5082,3 +5082,43 @@ kdump_get_qemucpustate(int cpu) return (QEMUCPUState *)nd->nt_qemu_percpu[cpu]; } #endif + +/* + * extract hardware specific device dumps from coredump. + */ +void +kdump_device_dump(int index, char *outfile, FILE *ofp) +{ + ulonglong offset; + void *elf_base; + + if (index >= nd->num_vmcoredd_notes) { + error(WARNING, "No device dump found at index: %d", index); + return; + } + + if (DUMPFILE_FORMAT(nd->flags) == KDUMP_ELF64) { + elf_base = (void *)nd->elf64; + } else if (DUMPFILE_FORMAT(nd->flags) == KDUMP_ELF32) { + elf_base = (void *)nd->elf32; + } else { + error(WARNING, "Unsupported Dumpfile Format: 0x%x", + DUMPFILE_FORMAT(nd->flags)); + return; + } + + fprintf(ofp, "%d) ", index); + offset = nd->nt_vmcoredd_array[index] - elf_base; + devdump_extract(nd->nt_vmcoredd_array[index], offset, outfile, ofp); +} + +/* + * list all hardware specific device dumps present in coredump. + */ +void kdump_device_dump_info(FILE *ofp) +{ + int i; + + for (i = 0; i < nd->num_vmcoredd_notes; i++) + kdump_device_dump(i, NULL, ofp); +} -- 1.8.3.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility